Não imediatamente visível, mas possível. O que você precisa fazer aqui é combinar seu documento de nível superior com o conjunto de comentários sem duplicá-lo. Aqui está uma abordagem para primeiro unir o conteúdo como duas matrizes em uma matriz singular e, em seguida,
$unwind
para agrupar o conteúdo:db.collection.aggregate([
{ "$group": {
"_id": "$_id",
"author": {
"$addToSet": {
"id": "$_id",
"author": "$author",
"votes": "$votes"
}
},
"comments": { "$first": "$comments" }
}},
{ "$project": {
"combined": { "$setUnion": [ "$author", "$comments" ] }
}},
{ "$unwind": "$combined" },
{ "$group": {
"_id": "$combined.author",
"votes": { "$sum": "$combined.votes" }
}},
{ "$sort": { "votes": -1 } }
])
O que dá a saída:
{ "_id" : "Jesse", "votes" : 148 }
{ "_id" : "Mirek", "votes" : 135 }
{ "_id" : "Leszke", "votes" : 13 }
Mesmo pulando o primeiro
$group
stage e fazer uma matriz combinada de uma maneira diferente:db.collection.aggregate([
{ "$project": {
"combined": {
"$setUnion": [
{ "$map": {
"input": { "$literal": ["A"] },
"as": "el",
"in": {
"author": "$author",
"votes": "$votes"
}
}},
"$comments"
]
}
}},
{ "$unwind": "$combined" },
{ "$group": {
"_id": "$combined.author",
"votes": { "$sum": "$combined.votes" }
}},
{ "$sort": { "votes": -1 } }
])
Esses usam operadores como
$setUnion
e até $map
que foram introduzidos a partir do MongoDB 2.6. Isso o torna mais simples, mas ainda pode ser feito em versões anteriores sem esses operadores, seguindo basicamente os mesmos princípios:db.collection.aggregate([
{ "$project": {
"author": 1,
"votes": 1,
"comments": 1,
"type": { "$const": ["A","B"] }
}},
{ "$unwind": "$type" },
{ "$unwind": "$comments" },
{ "$group": {
"_id": {
"$cond": [
{ "$eq": [ "$type", "A" ] },
{
"id": "$_id",
"author": "$author",
"votes": "$votes"
},
"$comments"
]
}
}},
{ "$group": {
"_id": "$_id.author",
"votes": { "$sum": "$_id.votes" }
}},
{ "$sort": { "votes": -1 } }
])
O
$const
não está documentado, mas está presente em todas as versões do MongoDB em que a estrutura de agregação está presente (de 2.2). MongoDB 2.6 introduzido $literal
que essencialmente se vincula ao mesmo código subjacente. Ele foi usado em dois casos aqui para fornecer um elemento de modelo para uma matriz ou como introduzir uma matriz para desenrolar a fim de fornecer uma "escolha binária" entre duas ações.