Ja, dit is een beetje moeilijker gezien het feit dat er meerdere arrays zijn, en als je beide tegelijkertijd probeert, krijg je een "cartesiaanse voorwaarde" waarbij de ene array de inhoud van de andere vermenigvuldigt.
Combineer daarom de array-inhoud aan het begin, wat waarschijnlijk aangeeft hoe u de gegevens in de eerste plaats zou moeten opslaan:
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) {
}
)
Dus via de eerste $project
ensceneer de $map
operators voegen de waarde "type" toe aan elk item van elke array. Niet dat het hier echt uitmaakt, aangezien alle items sowieso "uniek" zouden moeten verwerken, de $setUnion
operator "contateneert" elke array in een enkelvoudige array.
Zoals eerder vermeld, zou u waarschijnlijk in de eerste plaats op deze manier moeten opslaan.
Verwerk vervolgens $unwind
gevolgd door $group
, waarbij elke "pros" en "cons" vervolgens wordt geëvalueerd via $cond
to omdat het overeenkomt met "type", ofwel 1
. teruggeven of 0
waarbij de overeenkomst respectievelijk true/false
. is naar de $sum
aggregatie-accumulator.
Dit geeft u een "logische overeenkomst" om elk respectief "type" binnen de aggregatiebewerking te tellen volgens de gespecificeerde groeperingssleutels.