Er zijn een aantal manieren om dit te benaderen, afhankelijk van welk uitvoerformaat het beste bij uw behoeften past. De belangrijkste opmerking is dat met het "aggregatieraamwerk" zelf, kun je niet echt iets "cast" als een datum retourneren, maar je kunt waarden krijgen die gemakkelijk kunnen worden gereconstrueerd in een Date
object bij het verwerken van resultaten in uw API.
De eerste benadering is het gebruik van de "Date Aggregation Operators" beschikbaar voor het aggregatieraamwerk:
db.collection.aggregate([
{ "$match": {
"time": { "$gte": startDate, "$lt": endDate }
}},
{ "$group": {
"_id": {
"year": { "$year": "$time" },
"dayOfYear": { "$dayOfYear": "$time" },
"hour": { "$hour": "$time" },
"minute": {
"$subtract": [
{ "$minute": "$time" },
{ "$mod": [ { "$minute": "$time" }, 10 ] }
]
}
},
"count": { "$sum": 1 }
}}
])
Die een samengestelde sleutel retourneert voor _id
met alle gewenste waarden voor een "datum". Als alternatief, als het altijd maar binnen een "uur" is, gebruik dan gewoon het gedeelte "minuut" en bereken de werkelijke datum op basis van de startDate
van uw bereikselectie.
Of u kunt gewoon "Date-wiskunde" gebruiken om de milliseconden sinds "epoch" te krijgen, die opnieuw rechtstreeks aan een datumaannemer kunnen worden doorgegeven.
db.collection.aggregate([
{ "$match": {
"time": { "$gte": startDate, "$lt": endDate }
}},
{ "$group": {
"_id": {
"$subtract": [
{ "$subtract": [ "$time", new Date(0) ] },
{ "$mod": [
{ "$subtract": [ "$time", new Date(0) ] },
1000 * 60 * 10
]}
]
},
"count": { "$sum": 1 }
}}
])
In alle gevallen wat u niet doet wilt doen is gebruik $project
voordat u $group
daadwerkelijk toepast
. Als een "pijplijnfase", $project
moet door alle geselecteerde documenten "fietsen" en de inhoud "transformeren".
Dit kost tijd , en wordt toegevoegd aan het uitvoeringstotaal van de query. Je kunt je gewoon aanmelden bij de $group
direct zoals is getoond.
Of als je echt "puur" bent over een Date
object wordt geretourneerd zonder nabewerking, dan kunt u altijd "mapReduce" , aangezien de JavaScript-functies daadwerkelijk herschikken als een datum toestaan, maar langzamer dan het aggregatieraamwerk en natuurlijk zonder een cursorreactie:
db.collection.mapReduce(
function() {
var date = new Date(
this.time.valueOf()
- ( this.time.valueOf() % ( 1000 * 60 * 10 ) )
);
emit(date,1);
},
function(key,values) {
return Array.sum(values);
},
{ "out": { "inline": 1 } }
)
Je kunt echter het beste aggregatie gebruiken, omdat het transformeren van de reactie vrij eenvoudig is:
db.collection.aggregate([
{ "$match": {
"time": { "$gte": startDate, "$lt": endDate }
}},
{ "$group": {
"_id": {
"year": { "$year": "$time" },
"dayOfYear": { "$dayOfYear": "$time" },
"hour": { "$hour": "$time" },
"minute": {
"$subtract": [
{ "$minute": "$time" },
{ "$mod": [ { "$minute": "$time" }, 10 ] }
]
}
},
"count": { "$sum": 1 }
}}
]).forEach(function(doc) {
doc._id = new Date(doc._id);
printjson(doc);
})
En dan heb je de output van je intervalgroepering met echte Date
objecten.