Následující kanál by vám měl fungovat:
var pipeline = [
{
"$project": {
"title": 1, "body": 1,
"post_id": { "$ifNull": [ "$_post", "$_id" ] }
}
},
{
"$group": {
"_id": "$post_id",
"title": { "$first": "$title" },
"body": { "$first": "$body" },
"comments": {
"$push": {
"_id": "$_id",
"_post": "$post_id",
"body": "$body"
}
}
}
},
{
"$project": {
"title": 1, "body": 1,
"comments": {
"$setDifference": [
{
"$map": {
"input": "$comments",
"as": "el",
"in": {
"$cond": [
{ "$ne": [ "$$el._id", "$$el._post" ] },
"$$el",
false
]
}
}
},
[false]
]
}
}
}
];
Post.aggregate(pipeline, function (err, result) {
if (err) { /* handle error */ };
console.log(result);
});
Potrubí je strukturováno tak, že váš první krok, $project
fáze operátora, je promítnout pole post_id
být použit jako skupina podle klíče v další fázi procesu. Protože je vaše schéma hierarchické, budete toto pole potřebovat pro nadřazené/kořenové dokumenty. $ifNull
Operátor bude fungovat jako operátor sloučení a vrátí hodnotu nahrazení, pokud pole v dokumentech neexistuje.
Další krok kanálu, $group
pipeline stage se snaží data seskupit a zpracovat je. $group
Operátor kanálu je podobný klauzuli GROUP BY SQL. V SQL nemůžeme použít GROUP BY, pokud nepoužíváme některou z agregačních funkcí. Stejně tak musíme použít agregační funkci i v MongoDB. V tomto případě potřebujete $push
operátor k vytvoření pole komentářů. Ostatní pole se pak shromažďují pomocí $first
operátor.
Poslední krok zahrnuje přizpůsobení pole komentářů tak, že odstraníte dokument s podrobnostmi příspěvku, což rozhodně není typ komentáře. To je možné díky $setDifference
a $map
operátory. $map
operátor v podstatě vytvoří nové pole pole, které obsahuje hodnoty jako výsledek vyhodnocené logiky v podvýrazu ke každému prvku pole. $setDifference
operátor pak vrátí sadu s prvky, které se vyskytují v první sadě, ale ne ve druhé sadě; tj. provádí relativní doplněk druhé sady vzhledem k první. V tomto případě vrátí poslední comments
pole, které obsahuje prvky nesouvisející s nadřazenými dokumenty prostřednictvím _id
vlastnost.