Toto je spíše otázka toho, jak očekáváte, že bude výstup vypadat, protože jakýkoli agregovaný výsledek v podstatě potřebuje seskupovat na nejnižší úrovni a pak postupně seskupovat na vyšších „zrnách“, dokud není dosaženo největší úrovně („měsíc“). Tento druh implikuje data seskupená podle „měsíce“, pokud je nerozdělíte jinak.
V podstatě postupně $group
:
db.collection.aggregate([
// First total per day. Rounding dates with math here
{ "$group": {
"_id": {
"$add": [
{ "$subtract": [
{ "$subtract": [ "$createdAt", new Date(0) ] },
{ "$mod": [
{ "$subtract": [ "$createdAt", new Date(0) ] },
1000 * 60 * 60 * 24
]}
]},
new Date(0)
]
},
"week": { "$first": { "$week": "$createdAt" } },
"month": { "$first": { "$month": "$createdAt" } },
"total": { "$sum": "$num" }
}},
// Then group by week
{ "$group": {
"_id": "$week",
"month": { "$first": "$month" },
"days": {
"$push": {
"day": "$_id",
"total": "$total"
}
},
"total": { "$sum": "$total" }
}},
// Then group by month
{ "$group": {
"_id": "$month",
"weeks": {
"$push": {
"week": "$_id",
"total": "$total",
"days": "$days"
}
},
"total": { "$sum": "$total" }
}}
])
Takže každá úroveň po první, která se sčítá za den, je pak postupně vkládána do obsahu pole pro její "zaokrouhlenou" hodnotu a součty jsou pak sečteny také na této úrovni.
Pokud chcete plošší výstup s jedním záznamem za den, který obsahuje týdenní a měsíční součty a také celkový den, pak stačí připojit dva $unwind
příkazy do konce kanálu:
{ "$unwind": "$weeks" },
{ "$unwind": "$weeks.days" }
A volitelně $project
"tečkovaná" pole přejdou na něco ploššího a čitelného, pokud musíte.
Pokud tím překlenete „roky“, pak takovou operaci zahrňte do seskupovacího klíče alespoň od úrovně „týden“, abyste možná nekombinovali data z různých let a byla oddělena.
Je také mým obecným zájmem používat "matematiku s datem"
při zaokrouhlování dat, protože vrací Date
objekt, ale jak se používá na jiných úrovních než "den", můžete střídavě použít operátory agregace dat
místo toho.
Není potřeba mapReduce
protože je to docela intuitivní a v měsíci je omezený počet dní, což znamená, že limit BSON při vnořování polí do obsahu během agregace nebude porušen.