Isso faz o que você precisa. Eu normalizei os tempos nos dados para que eles se agrupassem (você poderia fazer algo assim). A ideia é
$group
e empurre o time
's e total
's em arrays separados. Então $unwind
a time
array, e você fez uma cópia dos totals
array para cada time
documento. Você pode então calcular o runningTotal
(ou algo como a média móvel) do array contendo todos os dados para tempos diferentes. O 'índice' gerado por $unwind
é o índice do array para o total
correspondente a essa time
. É importante $sort
antes de $unwind
ing, pois isso garante que as matrizes estejam na ordem correta. 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 ] } ] } },
}
},
]
);
Usei algo semelhante em uma coleção com ~80.000 documentos, agregando 63 resultados. Não tenho certeza de como isso funcionará em coleções maiores, mas descobri que realizar transformações (projeções, manipulações de matriz) em dados agregados não parece ter um grande custo de desempenho quando os dados são reduzidos a um tamanho gerenciável.