Question

Im essayant de recherche à travers une collection de groupe et des enregistrements par date de champ qui est un datetime.Je sais pymongo convertit ces type approprié sur le fond (ISODate ou quelque chose comme ça).

La Question est, depuis datetime objets ont la date, l'heure, le fuseau horaire..comment puis-je savoir le groupe de l'opérateur à utiliser que la partie date?Parce que sinon, je n'obtiens pas souhaité en regroupement depuis le temps, c'est de prévenir les enregistrements avec les mêmes jour, mois, année à être regroupés.

db.test.aggregate([
        {"$group": {
             "_id": "$date", 
             "count": {"$sum": 1}
        }},
        {"$limit": 10}])

Résultat:

{u'ok': 1.0,
 u'result': [
  {u'_id': datetime.datetime(2014, 2, 15, 18, 49, 9, tzinfo=<bson.tz_util.FixedOffset object at 0x318f210>),
   u'count': 1},
  {u'_id': datetime.datetime(2014, 2, 15, 18, 36, 38, tzinfo=<bson.tz_util.FixedOffset object at 0x318f210>),
   u'count': 1},
  {u'_id': datetime.datetime(2014, 2, 15, 18, 23, 56, tzinfo=<bson.tz_util.FixedOffset object at 0x318f210>),
   u'count': 1}]}

Il serait bon de contrôler les informations de datetime utilisé pour le groupe,

  • groupe par jour seulement
  • groupe par date et heure
  • groupe par la date, l'heure et les minutes
  • etc.

Est-il quelque chose comme:(ou une façon de dire à l'utilisation de la date uniquement)

db.test.aggregate([
          {"$group": {
              "_id": "$date.date()",
              "count": {"$sum": 1}
          }},
          {"$sort": "_id"}
])

Ou peut-être il ya une autre façon de composer avec tout cela, des idées?Merci.

Était-ce utile?

La solution

Oui.Vous pouvez utiliser l' Les Opérateurs De Date avec $substr et $concat pour lier tout cela ensemble.

db.test.aggregate([
    {"$group": {
        "_id" : { "$concat": [
            {"$substr": [{"$year": "$date"}, 0, 4 ]},
            "-",
            {"$substr": [{"$month": "$date"}, 0, 2 ]},
            "-",
            {"$substr": [{"$dayOfMonth": "$date"}, 0, 2 ]},
        ]},
        "count": {"$sum": 1 }
     }},
     {"$sort": { "_id": 1 }}
])

Vous pouvez utiliser seulement les opérateurs de dates et de faire un document comme dans:

"day": { 
    "year": {"$year": "$date" },
   "month": {"$month": "$date"}, 
   "day": {"$dayOfYear": "$date"}
}

Qui fonctionne tout aussi bien.Mais cela vous donne une belle chaîne.Cela rend l'utilisation du fait que $substr sera moulé en entier en chaîne de caractères.Si ce n'est jamais ajouté à la documentation.

Regardez le Les Opérateurs De Date documentation pour l'utilisation sur les autres intervalles de temps qui peuvent être utilisés sur les dates.


Mieux encore, utilisez la date de mathématiques, de retour d'un BFILS Date:

import datetime

db.test.aggregate([
    { "$group": {
        "_id": {
            "$add": [
               { "$subtract": [
                   { "$subtract": [ "$date", datetime.datetime.utcfromtimestamp(0) ] },
                   { "$mod": [
                       { "$subtract": [ "$date", datetime.datetime.utcfromtimestamp(0) ] },
                       1000 * 60 * 60 * 24
                   ]}
               ]},
               datetime.datetime.utcfromtimestamp(0)
           ]
        },
        "count": { "$sum": 1 }
    }},
    { "$sort": { "_id": 1 } }
])

Ici datetime.datetime.utcfromtimestamp(0) seront introduits dans le pipeline comme un BFILS Date représentant "de l'époque".Lorsque vous $subtract un BFILS Date à partir d'un autre la différence en millisecondes est retourné.Cela vous permet de "ronde" la date du jour actuel en soustrayant la $mod résultat pour obtenir le reste de millisecondes de différence à partir d'un jour.

La même chose est vraie de $add où ", ajoutant que" un BFILS Date à une valeur numérique entraînera une BFILS Date.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top