Ja, det här är lite svårare med tanke på att det finns flera arrayer, och om du försöker båda samtidigt får du ett "kartesiskt tillstånd" där en array multiplicerar innehållet i den andra.
Kombinera därför arrayinnehållet i början, vilket förmodligen indikerar hur du bör lagra data i första hand:
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) {
}
)
Så via det första $project
iscensätt $map
Operatörer lägger till värdet "type" till varje objekt i varje array. Inte för att det egentligen spelar någon roll här eftersom alla objekt ska bearbetas "unika" ändå, $setUnion
operatorn "kontatenerar" varje array till en singulär array.
Som nämnts tidigare bör du förmodligen lagra på detta sätt i första hand.
Bearbeta sedan $unwind
följt av $group
, där varje "för- och nackdelar" sedan utvärderas via $cond
till för att det matchar "typ", antingen returnerar 1
eller 0
där matchningen är respektive true/false
till $sum
aggregeringsackumulator.
Detta ger dig en "logisk matchning" för att räkna varje respektive "typ" inom aggregeringsoperationen enligt de angivna grupperingsnycklarna.