Estuvisteis muy unidos, pero claro $eq
simplemente devuelve un true/false
value, por lo que para hacer ese valor numérico necesitas $cond
:
db.collection(collectionName).aggregate([
{ "$group" : {
"_id": "$item",
"good_count": {
"$sum": {
"$cond": [ { "$eq": [ "$rating", "good" ] }, 1, 0]
}
},
"neutral_count":{
"$sum": {
"$cond": [ { "$eq": [ "$rating", "neutral" ] }, 1, 0 ]
}
},
"bad_count": {
"$sum": {
"$cond": [ { "$eq": [ "$rating", "bad" ] }, 1, 0 ]
}
}
}}
])
Como operador "ternario" $cond
toma una condición lógica como su primer argumento (si) y luego devuelve el segundo argumento donde la evaluación es true
(entonces) o el tercer argumento donde false
(demás). Esto hace true/false
regresa a 1
y 0
para alimentar a $sum
respectivamente.
También tenga en cuenta que "mayúsculas" es sensible para $eq
. Si tiene un caso variable, es probable que desee $toLower
en las expresiones:
"$cond": [ { "$eq": [ { "$toLower": "$rating" }, "bad" ] }, 1, 0 ]
En una nota ligeramente diferente, la siguiente agregación suele ser más flexible a los diferentes valores posibles y gira alrededor de las sumas condicionales en términos de rendimiento:
db.collection(collectionName).aggregate([
{ "$group": {
"_id": {
"item": "$item",
"rating": { "$toLower": "$rating" }
},
"count": { "$sum": 1 }
}},
{ "$group": {
"_id": "$_id.item",
"results": {
"$push": {
"rating": "$_id.rating",
"count": "$count"
}
}
}}
])
En cambio, eso daría un resultado como este:
{
"_id": "item_1"
"results":[
{ "rating": "good", "count": 12 },
{ "rating": "neutral", "count": 10 }
{ "rating": "bad", "count": 67 }
]
}
Es toda la misma información, pero no tenía que hacer coincidir explícitamente los valores y se ejecuta mucho más rápido de esta manera.