Följande pipeline bör fungera för dig:
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);
});
Pipelinen är strukturerad på ett sådant sätt att ditt första steg, $projekt
operatörsstadiet, är att projicera fältet post_id
ska användas som grupp för nyckel i nästa steg i pipeline. Eftersom ditt schema är hierarkiskt skulle du behöva det här fältet för överordnade/rotdokument. $ifNull
operatören kommer att fungera som sammansmältningsoperatör och returnera ersättningsvärdet om fältet inte finns i dokumenten.
Nästa steg i pipeline, code>$grupp
pipelinesteget försöker gruppera data för att bearbeta dem. $group
pipeline-operatorn liknar SQL:s GROUP BY-sats. I SQL kan vi inte använda GROUP BY om vi inte använder någon av aggregeringsfunktionerna. På samma sätt måste vi använda en aggregeringsfunktion i MongoDB också. I det här fallet behöver du $push
operatör för att skapa kommentarsfältet. De andra fälten ackumuleras sedan med $first
operatör.
Det sista steget innefattar att anpassa kommentarsfältet så att du tar bort dokumentet med inläggsdetaljerna, vilket definitivt inte är av en kommentarstyp. Detta görs möjligt genom $setDifference
och $map
operatörer. $map
Operatören skapar i huvudsak ett nytt arrayfält som innehåller värden som ett resultat av den utvärderade logiken i ett underuttryck till varje element i en array. $setDifference
operatorn returnerar sedan en uppsättning med element som förekommer i den första uppsättningen men inte i den andra uppsättningen; dvs. utför ett relativt komplement av den andra uppsättningen relativt den första. I det här fallet kommer den att returnera de sista kommentarerna
array som har element som inte är relaterade till de överordnade dokumenten via _id
egendom.