Sí, esto es un poco más difícil teniendo en cuenta que hay varios arreglos, y si prueba ambos al mismo tiempo, termina con una "condición cartesiana" en la que un arreglo multiplica el contenido del otro.
Por lo tanto, simplemente combine el contenido de la matriz al principio, lo que probablemente indica cómo debería almacenar los datos en primer lugar:
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) {
}
)
Entonces, a través del primer $project
organizar el $map
los operadores están agregando el valor de "tipo" a cada elemento de cada matriz. No es que realmente importe aquí, ya que todos los elementos deben procesarse como "únicos" de todos modos, el $setUnion
operador "contatena" cada arreglo en un arreglo singular.
Como se mencionó anteriormente, probablemente debería almacenar de esta manera en primer lugar.
Luego procesa $unwind
seguido de $group
, donde cada "pros" y "contras" se evalúa a través de $cond
a por su "tipo" coincidente, ya sea devolviendo 1
o 0
donde la coincidencia es respectivamente true/false
al $sum
acumulador de agregación.
Esto le da una "coincidencia lógica" para contar cada "tipo" respectivo dentro de la operación de agregación según las claves de agrupación especificadas.