MongoDB
 sql >> Base de Dados >  >> NoSQL >> MongoDB

Como agrupar postagens aninhadas com a estrutura de agregação do MongoDB?


O seguinte pipeline deve funcionar para você:
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);
});

O pipeline é estruturado de forma que sua primeira etapa, o $project estágio do operador, é projetar o campo post_id para ser usado como o grupo por chave no próximo estágio do pipeline. Como seu esquema é hierárquico, você precisaria desse campo para documentos pai/raiz. O $ifNull operador atuará como operador de coalescência e retornará o valor de substituição caso o campo não exista nos documentos.

A próxima etapa do pipeline, o $grupo O estágio de pipeline tenta agrupar os dados para processá-los. O $group operador de pipeline é semelhante à cláusula GROUP BY do SQL. Em SQL, não podemos usar GROUP BY a menos que usemos qualquer uma das funções de agregação. Da mesma forma, temos que usar uma função de agregação no MongoDB também. Nesse caso, você precisa do $push operador para criar a matriz de comentários. Os outros campos são então acumulados usando o $primeiro operador.

A etapa final envolve ajustar a matriz de comentários para que você remova o documento com os detalhes da postagem, que definitivamente não é um tipo de comentário. Isso é possível por meio do $setDifference e $map operadores. O $map Essencialmente, o operador cria um novo campo de matriz que contém valores como resultado da lógica avaliada em uma subexpressão para cada elemento de uma matriz. O $setDifference operador então retorna um conjunto com elementos que aparecem no primeiro conjunto, mas não no segundo conjunto; isto é, realiza um complemento relativo do segundo conjunto em relação ao primeiro. Nesse caso, ele retornará os comentários finais array que possui elementos não relacionados aos documentos pai através do _id propriedade.