Да, това е малко по-трудно, като се има предвид, че има множество масиви и ако опитате и двата едновременно, ще получите „декартово условие“, при което единият масив умножава съдържанието на другия.
Затова просто комбинирайте съдържанието на масива в началото, което вероятно показва как трябва да съхранявате данните на първо място:
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) {
}
)
Така че чрез първия $project
етап на $map
операторите добавят стойността "тип" към всеки елемент от всеки масив. Не че това наистина има значение тук, тъй като всички елементи така или иначе трябва да обработват "уникални", $setUnion
операторът "контатенира" всеки масив в единичен масив.
Както споменахме по-рано, вероятно трябва да съхранявате по този начин на първо място.
След това обработете $unwind
последвано от $group
, където всеки „за“ и „против“ след това се оценява чрез $cond
до за това, че съответства на "тип", или връща 1
или 0
където съвпадението е съответно true/false
към $sum
акумулатор на агрегация.
Това ви дава „логическо съвпадение“, за да преброите всеки съответен „тип“ в рамките на операцията за агрегиране според посочените ключове за групиране.