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

Contagem agregada do MongoDB de itens em duas matrizes em documentos diferentes?


Sim, isso é um pouco mais difícil, considerando que existem vários arrays e, se você tentar os dois ao mesmo tempo, acaba com uma "condição cartesiana" em que um array multiplica o conteúdo do outro.

Portanto, basta combinar o conteúdo do array no início, o que provavelmente indica como você deve armazenar os dados em primeiro lugar:
Model.aggregate(
    [
        { "$project": {
            "company": 1,
            "model": 1,
            "data": {
                "$setUnion": [
                    { "$map": {
                        "input": "$pros",
                        "as": "pro",
                        "in": {
                            "type": { "$literal": "pro" },
                            "value": "$$pro"
                        }
                    }},
                    { "$map": {
                        "input": "$cons",
                        "as": "con",
                        "in": {
                            "type": { "$literal": "con" },
                            "value": "$$con"
                        }
                    }}
                ]
            }
        }},
        { "$unwind": "$data" }
        { "$group": {
            "_id": { 
                "company": "$company",
                "model": "$model",
                "tag": "$data.value"
            },
            "pros": { 
                "$sum": { 
                    "$cond": [
                        { "$eq": [ "$data.type", "pro" ] },
                        1,
                        0
                    ]
                }
            },
            "cons": { 
                "$sum": { 
                    "$cond": [
                        { "$eq": [ "$data.type", "con" ] },
                        1,
                        0
                    ]
                }
            }
        }
    ], 
    function(err,result) {

    }
)

Então, através do primeiro $project preparar o $map os operadores estão adicionando o valor "type" a cada item de cada array. Não que isso realmente importe aqui, pois todos os itens devem processar "único" de qualquer maneira, o $setUnion operador "contate" cada array em um array singular.

Como mencionado anteriormente, você provavelmente deveria estar armazenando dessa maneira em primeiro lugar.

Em seguida, processe $unwind seguido por $group , em que cada "prós" e "contras" é então avaliado por meio de $cond para o "tipo" correspondente, retornando 1 ou 0 onde a correspondência é respectivamente true/false para o $sum acumulador de agregação.

Isso fornece uma "correspondência lógica" para contar cada "tipo" respectivo na operação de agregação de acordo com as chaves de agrupamento especificadas.