Du måste villkorligt bestämma grupperingsnyckeln baserat på var det aktuella datumet ligger mellan intervallet. Detta uppnås i princip via $cond
med kapslade villkor och den logiska varianten av $lt
:
// work out dates somehow
var today = new Date(),
oneDay = ( 1000 * 60 * 60 * 24 ),
thirtyDays = new Date( today.valueOf() - ( 30 * oneDay ) ),
fifteenDays = new Date( today.valueOf() - ( 15 * oneDay ) ),
sevenDays = new Date( today.valueOf() - ( 7 * oneDay ) );
db.collection.aggregate([
{ "$match": {
"date": { "$gte": thirtyDays }
}},
{ "$group": {
"_id": {
"$cond": [
{ "$lt": [ "$date", fifteenDays ] },
"16-30",
{ "$cond": [
{ "$lt": [ "$date", sevenDays ] },
"08-15",
"01-07"
]}
]
},
"count": { "$sum": 1 },
"totalValue": { "$sum": "$value" }
}}
])
Som $cond
är en ternär operator, utvärderas det första villkoret för att se om villkoret är sant, och när det är sant returneras det andra argumentet annars returneras det tredje när det är falskt. Så genom att kapsla ytterligare en $cond
i det falska fallet får du det logiska testet på var datumet infaller, antingen "mindre än 15-dagarsdatumet" vilket betyder att det är i det äldsta intervallet, eller "mindre än 7 dagar" som betyder mellanintervallet, eller så är det naturligtvis i det senaste sortimentet.
Jag sätter bara prefixet för siffrorna här mindre än 10 med en 0
så det ger dig något att sortera på om du vill, eftersom utmatningen av "nycklar" i $group
är inte i sig beställt.
Men det är så du gör detta i en enda fråga. Du räknar bara ut vad grupperingsnyckeln ska vara baserat på var datumet infaller och ackumuleras för varje nyckel.