Ci sono un paio di modi per farlo.
Il primo è con gli operatori di aggregazione di date, che consentono di sezionare i valori di "data" nei documenti. Specificamente per il "raggruppamento" come intento 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 }
}}
])
Il secondo modo consiste nell'usare un piccolo trucco su quando un oggetto data viene sottratto (o altre operazioni matematiche dirette) da un altro oggetto data, quindi il risultato è un valore numerico che rappresenta il timestamp di epoch in millisecondi tra i due oggetti. Quindi, semplicemente usando la data di epoch si ottiene la rappresentazione dei millisecondi di epoch. Quindi usa la matematica delle date per l'intervallo:
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 }
}}
])
Quindi dipende dal tipo di formato di output che desideri per l'intervallo di raggruppamento. Entrambi rappresentano sostanzialmente la stessa cosa e hanno dati sufficienti per ricostruire come un oggetto "data" nel tuo codice.
Puoi inserire qualsiasi altra cosa desideri nella parte "operatore di raggruppamento" dopo il raggruppamento _id
. Sto solo usando l'esempio di base del "contare" al posto di qualsiasi affermazione reale da parte tua su ciò che vuoi veramente fare.
MongoDB 4.xe versioni successive
Ci sono state alcune aggiunte a Date Aggregation Operators dalla stesura originale, ma da MongoDB 4.0 ci sarà un vero e proprio "casting di tipi" in contrasto con i trucchi matematici di base fatti qui con la conversione della data BSON.
Ad esempio possiamo usare $toLong
e $toDate
come nuovi aiutanti qui:
db.collection.aggregate([
{ "$group": {
"_id": {
"$toDate": {
"$subtract": [
{ "$toLong": "$created_at" },
{ "$mod": [ { "$toLong": "$created_at" }, 1000 * 60 * 15 ] }
]
}
},
"count": { "$sum": 1 }
}}
])
È un po' più breve e non richiede la definizione di una data BSON esterna per il valore "epoca" come costante nella definizione della pipeline, quindi è abbastanza coerente per tutte le implementazioni del linguaggio.
Questi sono solo due dei metodi "helper" per la conversione del tipo che si ricollegano tutti a $convert
metodo, che è una forma "più lunga" dell'implementazione che consente la gestione personalizzata su null
o errore nella conversione.
È anche possibile con tale casting ottenere la Date
informazioni da ObjectId
della chiave primaria, in quanto questa sarebbe una fonte affidabile di data di "creazione":
db.collection.aggregate([
{ "$group": {
"_id": {
"$toDate": {
"$subtract": [
{ "$toLong": { "$toDate": "$_id" } },
{ "$mod": [ { "$toLong": { "$toDate": "$_id" } }, 1000 * 60 * 15 ] }
]
}
},
"count": { "$sum": 1 }
}}
])
Quindi i "tipi di cast" con questo tipo di conversione possono essere uno strumento piuttosto potente.
Avviso - ObjectId
i valori sono limitati alla precisione al secondo solo per il valore temporale interno che costituisce parte dei loro dati consentendo il $toDate
conversione. L'effettivo "tempo" inserito molto probabilmente dipende dal driver in uso. Dove precisione è obbligatorio, si consiglia comunque di utilizzare un campo Data BSON discreto invece di fare affidamento su ObjectId
valori.