No inmediatamente visible pero posible. Lo que debe hacer aquí es combinar su documento de nivel superior con la matriz de comentarios sin duplicarlo. Aquí hay un enfoque para unir primero el contenido como dos matrices en una matriz singular, luego $unwind
para agrupar el contenido:
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 } }
])
Lo que da la salida:
{ "_id" : "Jesse", "votes" : 148 }
{ "_id" : "Mirek", "votes" : 135 }
{ "_id" : "Leszke", "votes" : 13 }
Incluso saltándose el primer $group
etapa y hacer una matriz combinada de una manera 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 } }
])
Esos usan operadores como $setUnion
e incluso $map
que se introdujeron a partir de MongoDB 2.6. Esto lo hace más simple, pero aún se puede hacer en versiones anteriores que carecen de esos operadores, siguiendo los mismos principios:
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 } }
])
El $const
no está documentado pero está presente en todas las versiones de MongoDB donde está presente el marco de agregación (desde 2.2). MongoDB 2.6 presentó $literal
que esencialmente se vincula al mismo código subyacente. Se ha utilizado en dos casos aquí para proporcionar un elemento de plantilla para una matriz o para introducir una matriz para desenrollar con el fin de proporcionar una "elección binaria" entre dos acciones.