Ja, das ist etwas schwieriger, wenn man bedenkt, dass es mehrere Arrays gibt, und wenn Sie beide gleichzeitig versuchen, erhalten Sie eine "kartesische Bedingung", bei der ein Array den Inhalt des anderen multipliziert.
Kombinieren Sie daher am Anfang einfach den Array-Inhalt, der wahrscheinlich anzeigt, wie Sie die Daten überhaupt speichern sollten:
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) {
}
)
Also über den ersten $project
Stellen Sie den $map
bereit
Operatoren fügen den "Typ"-Wert zu jedem Element jedes Arrays hinzu. Nicht, dass es hier wirklich wichtig wäre, da alle Artikel sowieso "unique" verarbeiten sollten, der $setUnion
Operator "verdichtet" jedes Array zu einem einzelnen Array.
Wie bereits erwähnt, sollten Sie wahrscheinlich von Anfang an auf diese Weise speichern.
Dann verarbeiten Sie $unwind
gefolgt von $group
, wobei jedes „Pro“ und „Contra“ dann über $cond
to für den übereinstimmenden "Typ", wobei entweder 1
zurückgegeben wird oder 0
wobei die Übereinstimmung jeweils true/false
ist zu $sum
Aggregationsakkumulator.
Dadurch erhalten Sie eine „logische Übereinstimmung“, um jeden jeweiligen „Typ“ innerhalb der Aggregationsoperation gemäß den angegebenen Gruppierungsschlüsseln zu zählen.