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.