MongoDB
 sql >> Base de données >  >> NoSQL >> MongoDB

Comment regrouper les publications imbriquées avec le framework d'agrégation MongoDB ?

Le pipeline suivant devrait fonctionner pour vous :

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

Le pipeline est structuré de telle manière que votre première étape, le $project l'étape de l'opérateur, consiste à projeter le champ post_id à utiliser comme groupe par clé dans la prochaine étape du pipeline. Étant donné que votre schéma est hiérarchique, vous aurez besoin de ce champ pour les documents parent/racine. Le $ifNull agira comme opérateur de fusion et renverra la valeur de remplacement si le champ n'existe pas dans les documents.

La prochaine étape du pipeline, le $group l'étape pipeline essaie de regrouper les données pour les traiter. Le $group L'opérateur de pipeline est similaire à la clause GROUP BY de SQL. En SQL, nous ne pouvons pas utiliser GROUP BY à moins d'utiliser l'une des fonctions d'agrégation. De la même manière, nous devons également utiliser une fonction d'agrégation dans MongoDB. Dans ce cas, vous avez besoin de $push opérateur pour créer le tableau de commentaires. Les autres champs sont ensuite accumulés en utilisant le $first opérateur.

La dernière étape consiste à filtrer le tableau des commentaires afin de supprimer le document avec les détails de la publication, qui n'est certainement pas de type commentaire. Ceci est rendu possible grâce à $setDifference et $map les opérateurs. Le $map L'opérateur crée essentiellement un nouveau champ de tableau qui contient des valeurs résultant de la logique évaluée dans une sous-expression pour chaque élément d'un tableau. Le $setDifference L'opérateur renvoie alors un ensemble avec des éléments qui apparaissent dans le premier ensemble mais pas dans le second ensemble ; c'est-à-dire effectue un complément relatif du deuxième ensemble par rapport au premier. Dans ce cas, il renverra les comments finaux tableau qui a des éléments non liés aux documents parents via le _id propriété.