sql >> Base de Datos >  >> NoSQL >> MongoDB

¿Cómo agrupar publicaciones anidadas con el marco de agregación de MongoDB?

La siguiente canalización debería funcionar para usted:

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 tubería está estructurada de tal manera que su primer paso, el $project etapa del operador, es proyectar el campo post_id para ser utilizado como el grupo por clave en la siguiente etapa de canalización. Dado que su esquema es jerárquico, necesitaría este campo para documentos principales/raíz. El $ifNull El operador actuará como el operador coalesce y devolverá el valor de reemplazo si el campo no existe en los documentos.

El siguiente paso de canalización, el $group etapa de canalización intenta agrupar los datos para procesarlos. El $group El operador de canalización es similar a la cláusula GROUP BY de SQL. En SQL, no podemos usar GROUP BY a menos que usemos alguna de las funciones de agregación. De la misma manera, también tenemos que usar una función de agregación en MongoDB. En este caso, necesita el $push operador para crear la matriz de comentarios. Luego, los otros campos se acumulan usando $first operador.

El paso final consiste en ajustar la matriz de comentarios para que elimine el documento con los detalles de la publicación, que definitivamente no es un tipo de comentario. Esto es posible a través de $setDifference y $map operadores. El $map En esencia, el operador crea un nuevo campo de matriz que contiene valores como resultado de la lógica evaluada en una subexpresión para cada elemento de una matriz. El $setDifference el operador luego devuelve un conjunto con elementos que aparecen en el primer conjunto pero no en el segundo conjunto; es decir, realiza un complemento relativo del segundo conjunto en relación con el primero. En este caso devolverá los comments finales matriz que tiene elementos no relacionados con los documentos principales a través de _id propiedad.