Tak, jest to nieco trudniejsze, biorąc pod uwagę, że istnieje wiele tablic, a jeśli spróbujesz obu jednocześnie, otrzymasz „warunek kartezjański”, w którym jedna tablica mnoży zawartość drugiej.
Dlatego po prostu połącz zawartość tablicy na początku, co prawdopodobnie wskazuje, w jaki sposób powinieneś przechowywać dane:
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) {
}
)
Tak więc za pośrednictwem pierwszego $project
przygotuj $map
operatorzy dodają wartość "typ" do każdego elementu każdej tablicy. Nie, żeby to naprawdę miało znaczenie, ponieważ wszystkie elementy i tak powinny być przetwarzane jako „unikalne”, $setUnion
operator "zawiera" każdą tablicę w pojedynczą tablicę.
Jak wspomniano wcześniej, prawdopodobnie powinieneś przechowywać w ten sposób.
Następnie przetwórz $unwind
po którym następuje $group
, gdzie każdy „za” i „przeciw” jest następnie oceniany przez $cond
dla pasującego "typu", zwracając 1
lub 0
gdzie dopasowanie to odpowiednio true/false
do $sum
akumulator agregacji.
Daje to „logiczne dopasowanie” do zliczania każdego odpowiedniego „typu” w ramach operacji agregacji zgodnie z określonymi kluczami grupowania.