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

MongoDB conteggio aggregato di elementi in due array su documenti diversi?

Sì, è un po' più difficile considerando che ci sono più array e se li provi entrambi allo stesso tempo finisci con una "condizione cartesiana" in cui un array moltiplica il contenuto dell'altro.

Pertanto, è sufficiente combinare il contenuto dell'array all'inizio, che probabilmente indica come archiviare i dati in primo luogo:

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) {

    }
)

Quindi tramite il primo $project mette in scena il $map gli operatori aggiungono il valore "tipo" a ogni elemento di ogni matrice. Non che qui importi davvero, poiché tutti gli elementi dovrebbero comunque essere elaborati "unici", il $setUnion l'operatore "contatta" ogni array in un array singolare.

Come accennato in precedenza, probabilmente dovresti archiviare in questo modo in primo luogo.

Quindi elaborare $unwind seguito da $group , in cui ogni "pro" e "contro" viene quindi valutato tramite $cond a perché corrisponde a "tipo", restituendo 1 o 0 dove la corrispondenza è rispettivamente true/false al $sum accumulatore di aggregazione.

Questo ti dà una "corrispondenza logica" per contare ogni rispettivo "tipo" all'interno dell'operazione di aggregazione secondo le chiavi di raggruppamento specificate.