Nicht sofort sichtbar aber möglich. Was Sie hier tun müssen, ist, Ihr Dokument der obersten Ebene mit der Reihe von Kommentaren zu kombinieren, ohne es zu duplizieren. Hier ist ein Ansatz, um den Inhalt zuerst als zwei Arrays zu einem einzigen Array zusammenzufügen, dann $unwind
um den Inhalt zu gruppieren:
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 } }
])
Was die Ausgabe ergibt:
{ "_id" : "Jesse", "votes" : 148 }
{ "_id" : "Mirek", "votes" : 135 }
{ "_id" : "Leszke", "votes" : 13 }
Sogar beim Überspringen des ersten $group
Stufe und Erstellen eines kombinierten Arrays auf andere Weise:
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 } }
])
Diese verwenden Operatoren wie $setUnion
und sogar $map
die ab MongoDB 2.6 eingeführt wurden. Das macht es einfacher, aber es kann immer noch in früheren Versionen durchgeführt werden, denen diese Operatoren fehlen, und zwar nach den gleichen Prinzipien:
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 } }
])
Der $const
ist undokumentiert, aber in allen Versionen von MongoDB vorhanden, in denen das Aggregationsframework vorhanden ist ( ab 2.2 ). MongoDB 2.6 eingeführt $literal
die im Wesentlichen mit demselben zugrunde liegenden Code verknüpft ist. Es wurde hier in zwei Fällen verwendet, um entweder ein Vorlagenelement für ein Array bereitzustellen oder um ein Array zum Entladen einzuführen, um eine "binäre Wahl" zwischen zwei Aktionen bereitzustellen.