Pas immédiatement visible mais possible. Ce que vous devez faire ici est de combiner votre document de niveau supérieur avec le tableau de commentaires sans le dupliquer. Voici une approche pour joindre d'abord le contenu en deux tableaux dans un tableau singulier, puis $unwind
pour regrouper le contenu :
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 } }
])
Ce qui donne la sortie :
{ "_id" : "Jesse", "votes" : 148 }
{ "_id" : "Mirek", "votes" : 135 }
{ "_id" : "Leszke", "votes" : 13 }
Même en sautant le premier $group
scène et créer un tableau combiné d'une manière différente :
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 } }
])
Ceux-ci utilisent des opérateurs tels que $setUnion
et même $map
qui ont été introduits à partir de MongoDB 2.6. Cela le rend plus simple, mais cela peut toujours être fait dans les versions antérieures dépourvues de ces opérateurs, en suivant à peu près les mêmes principes :
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 } }
])
Le $const
est non documenté mais présent dans toutes les versions de MongoDB où le framework d'agrégation est présent (à partir de 2.2). MongoDB 2.6 a introduit $literal
qui est essentiellement lié au même code sous-jacent. Il a été utilisé dans deux cas ici soit pour fournir un élément de modèle pour un tableau, soit pour introduire un tableau à dérouler afin de fournir un "choix binaire" entre deux actions.