Není to hned vidět, ale je to možné. Zde musíte zkombinovat dokument nejvyšší úrovně s řadou komentářů, aniž byste jej duplikovali. Zde je postup, jak nejprve spojit obsah jako dvě pole do singulárního pole a poté $unwind
pro seskupení obsahu:
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 } }
])
Což dává výstup:
{ "_id" : "Jesse", "votes" : 148 }
{ "_id" : "Mirek", "votes" : 135 }
{ "_id" : "Leszke", "votes" : 13 }
Dokonce i jako přeskočení první $group
fázi a vytvoření kombinovaného pole jiným způsobem:
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 } }
])
Ty používají operátory jako $setUnion
a dokonce $map
které byly představeny od MongoDB 2.6. Díky tomu je to jednodušší, ale stále to lze provést v dřívějších verzích bez těchto operátorů, a to podle téměř stejných principů:
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 } }
])
$const
je nezdokumentovaný, ale je přítomen ve všech verzích MongoDB, kde je přítomen agregační rámec (od 2.2). MongoDB 2.6 představen $literal
který v podstatě odkazuje na stejný základní kód. Byl zde použit ve dvou případech buď k poskytnutí prvku šablony pro pole, nebo jako zavedení pole k uvolnění za účelem poskytnutí „binární volby“ mezi dvěma akcemi.