MongoDB
 sql >> Datenbank >  >> NoSQL >> MongoDB

Wie gruppiert man verschachtelte Posts mit dem MongoDB-Aggregationsframework?

Die folgende Pipeline sollte für Sie funktionieren:

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);
});

Die Pipeline ist so aufgebaut, dass Ihr erster Schritt, der $project Operatorstufe, ist das Feld post_id zu projizieren als Gruppieren nach Schlüssel in der nächsten Pipelinestufe verwendet werden. Da Ihr Schema hierarchisch ist, benötigen Sie dieses Feld für übergeordnete/Stammdokumente. Der $ifNull Der Operator fungiert als Koaleszenzoperator und gibt den Ersatzwert zurück, wenn das Feld nicht in den Dokumenten vorhanden ist.

Der nächste Pipeline-Schritt, der $group Die Pipeline-Phase versucht, die Daten zu gruppieren, um sie zu verarbeiten. Der $group Der Pipelineoperator ähnelt der GROUP BY-Klausel von SQL. In SQL können wir GROUP BY nicht verwenden, es sei denn, wir verwenden eine der Aggregationsfunktionen. Auf die gleiche Weise müssen wir auch in MongoDB eine Aggregationsfunktion verwenden. In diesem Fall benötigen Sie den $push -Operator zum Erstellen des Kommentar-Arrays. Die anderen Felder werden dann mithilfe von $first Betreiber.

Der letzte Schritt besteht darin, das Kommentar-Array zu filtern, sodass Sie das Dokument mit den Beitragsdetails entfernen, das definitiv kein Kommentartyp ist. Dies wird durch $setDifference und $map Betreiber. Der $map -Operator erstellt im Wesentlichen ein neues Array-Feld, das Werte als Ergebnis der ausgewerteten Logik in einem Unterausdruck für jedes Element eines Arrays enthält. Der $setDifference Der Operator gibt dann eine Menge mit Elementen zurück, die in der ersten Menge, aber nicht in der zweiten Menge vorkommen; d.h. führt eine relative Ergänzung des zweiten Satzes relativ zum ersten durch. In diesem Fall werden die abschließenden Kommentare zurückgegeben Array, das Elemente enthält, die sich nicht über die _id auf die übergeordneten Dokumente beziehen Eigentum.