MongoDB
 sql >> Database >  >> NoSQL >> MongoDB

Come raggruppare i post nidificati con il framework di aggregazione MongoDB?

La seguente pipeline dovrebbe funzionare per te:

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

La pipeline è strutturata in modo tale che il tuo primo passo, il $project fase operatore, è quello di proiettare il campo post_id da utilizzare come gruppo per chiave nella fase successiva della pipeline. Poiché il tuo schema è gerarchico, avresti bisogno di questo campo per i documenti padre/root. Il $ifNull l'operatore fungerà da operatore coalescente e restituirà il valore sostitutivo se il campo non esiste nei documenti.

Il passaggio successivo della pipeline, il $group la fase della pipeline tenta di raggruppare i dati per elaborarli. Il $group l'operatore della pipeline è simile alla clausola GROUP BY di SQL. In SQL, non possiamo utilizzare GROUP BY a meno che non utilizziamo una delle funzioni di aggregazione. Allo stesso modo, dobbiamo usare anche una funzione di aggregazione in MongoDB. In questo caso è necessario il $push operatore per creare la matrice dei commenti. Gli altri campi vengono quindi accumulati utilizzando $first operatore.

Il passaggio finale prevede l'adattamento dell'array dei commenti in modo da rimuovere il documento con i dettagli del post, che sicuramente non è di un tipo di commento. Ciò è possibile tramite $setDifference e $map operatori. Il $map in sostanza, l'operatore crea un nuovo campo di matrice che contiene i valori come risultato della logica valutata in una sottoespressione per ciascun elemento di una matrice. Il $setDifference l'operatore restituisce quindi un insieme con elementi che appaiono nel primo insieme ma non nel secondo insieme; cioè esegue un complemento relativo del secondo insieme rispetto al primo. In questo caso restituirà i comments finali array che ha elementi non correlati ai documenti principali tramite _id proprietà.