Dit doet wat je nodig hebt. Ik heb de tijden in de gegevens genormaliseerd, zodat ze zich groeperen (je zou zoiets als dit kunnen doen). Het idee is om $group
en druk op de time
's en total
's in afzonderlijke arrays. Dan $unwind
de time
array, en je hebt een kopie gemaakt van de totals
array voor elke time
document. U kunt dan het runningTotal
. berekenen (of zoiets als het voortschrijdend gemiddelde) uit de array die alle gegevens voor verschillende tijden bevat. De 'index' gegenereerd door $unwind
is de array-index voor het total
corresponderend met die time
. Het is belangrijk om $sort
voor $unwind
omdat dit ervoor zorgt dat de arrays in de juiste volgorde staan.
db.temp.aggregate(
[
{
'$group': {
'_id': '$time',
'total': { '$sum': '$value' }
}
},
{
'$sort': {
'_id': 1
}
},
{
'$group': {
'_id': 0,
'time': { '$push': '$_id' },
'totals': { '$push': '$total' }
}
},
{
'$unwind': {
'path' : '$time',
'includeArrayIndex' : 'index'
}
},
{
'$project': {
'_id': 0,
'time': { '$dateToString': { 'format': '%Y-%m-%d', 'date': '$time' } },
'total': { '$arrayElemAt': [ '$totals', '$index' ] },
'runningTotal': { '$sum': { '$slice': [ '$totals', { '$add': [ '$index', 1 ] } ] } },
}
},
]
);
Ik heb iets soortgelijks gebruikt voor een verzameling met ~80 000 documenten, samen opgeteld tot 63 resultaten. Ik weet niet zeker hoe goed het zal werken op grotere collecties, maar ik heb ontdekt dat het uitvoeren van transformaties (projecties, arraymanipulaties) op geaggregeerde gegevens geen hoge prestatiekosten lijkt te hebben als de gegevens eenmaal zijn teruggebracht tot een beheersbare omvang.