Il existe plusieurs façons de procéder.
Le premier concerne les opérateurs d'agrégation de dates, qui vous permettent de disséquer les valeurs de "date" dans les documents. Spécifiquement pour "grouper" comme intention principale :
db.collection.aggregate([
{ "$group": {
"_id": {
"year": { "$year": "$created_at" },
"dayOfYear": { "$dayOfYear": "$created_at" },
"hour": { "$hour": "$created_at" },
"interval": {
"$subtract": [
{ "$minute": "$created_at" },
{ "$mod": [{ "$minute": "$created_at"}, 15] }
]
}
}},
"count": { "$sum": 1 }
}}
])
La deuxième méthode consiste à utiliser une petite astuce lorsqu'un objet date est soustrait (ou une autre opération mathématique directe) d'un autre objet date, puis le résultat est une valeur numérique représentant l'époque en millisecondes d'horodatage entre les deux objets. Donc, en utilisant simplement la date d'époque, vous obtenez la représentation de l'époque en millisecondes. Utilisez ensuite les calculs de date pour l'intervalle :
db.collection.aggregate([
{ "$group": {
"_id": {
"$subtract": [
{ "$subtract": [ "$created_at", new Date("1970-01-01") ] },
{ "$mod": [
{ "$subtract": [ "$created_at", new Date("1970-01-01") ] },
1000 * 60 * 15
]}
]
},
"count": { "$sum": 1 }
}}
])
Cela dépend donc du type de format de sortie que vous souhaitez pour l'intervalle de regroupement. Les deux représentent fondamentalement la même chose et ont suffisamment de données pour être reconstruites en tant qu'objet "date" dans votre code.
Vous pouvez mettre tout ce que vous voulez dans la partie "opérateur de regroupement" après le regroupement _id
. J'utilise simplement l'exemple de base "compter" au lieu de toute déclaration réelle de vous-même sur ce que vous voulez vraiment faire.
MongoDB 4.x et versions ultérieures
Il y a eu quelques ajouts aux opérateurs d'agrégation de dates depuis l'écriture originale, mais à partir de MongoDB 4.0, il y aura une "vraie coulée de types" par opposition aux astuces mathématiques de base effectuées ici avec la conversion de date BSON.
Par exemple, nous pouvons utiliser $toLong
et $toDate
en tant que nouveaux assistants ici :
db.collection.aggregate([
{ "$group": {
"_id": {
"$toDate": {
"$subtract": [
{ "$toLong": "$created_at" },
{ "$mod": [ { "$toLong": "$created_at" }, 1000 * 60 * 15 ] }
]
}
},
"count": { "$sum": 1 }
}}
])
C'est un peu plus court et ne nécessite pas de définir une date BSON externe pour la valeur "epoch" en tant que constante dans la définition du pipeline, donc c'est assez cohérent pour toutes les implémentations de langage.
Ce ne sont que deux des méthodes "d'assistance" pour la conversion de type qui sont toutes liées à $convert
méthode, qui est une forme "plus longue" de l'implémentation permettant une gestion personnalisée sur null
ou erreur de conversion.
Il est même possible avec un tel casting d'obtenir la Date
informations de l'ObjectId
de la clé primaire, car il s'agirait d'une source fiable de date de "création" :
db.collection.aggregate([
{ "$group": {
"_id": {
"$toDate": {
"$subtract": [
{ "$toLong": { "$toDate": "$_id" } },
{ "$mod": [ { "$toLong": { "$toDate": "$_id" } }, 1000 * 60 * 15 ] }
]
}
},
"count": { "$sum": 1 }
}}
])
Ainsi, "casting types" avec ce type de conversion peut être un outil assez puissant.
Avertissement -
ObjectId
les valeurs sont limitées à une précision à la seconde uniquement pour la valeur de temps interne qui fait partie de leurs données permettant le$toDate
conversion. Le "temps" réellement inséré dépend très probablement du pilote utilisé. Où la précision est obligatoire, il est toujours recommandé d'utiliser un champ de date BSON discret au lieu de s'appuyer surObjectId
valeurs.