Eri molto vicino, ma ovviamente $eq
restituisce solo un true/false
value, quindi per rendere quel numero è necessario $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 ]
}
}
}}
])
Come operatore "ternario" $cond
accetta una condizione logica come primo argomento (if) e quindi restituisce il secondo argomento in cui la valutazione è true
(quindi) o il terzo argomento dove false
(altro). Questo rende true/false
ritorna in 1
e 0
per alimentare $sum
rispettivamente.
Nota anche che "case" è sensibile per $eq
. Se hai diverse maiuscole, probabilmente vorrai $toLower
nelle espressioni:
"$cond": [ { "$eq": [ { "$toLower": "$rating" }, "bad" ] }, 1, 0 ]
In una nota leggermente diversa, la seguente aggregazione è solitamente più flessibile rispetto a diversi valori possibili e gira intorno alle somme condizionali in termini di prestazioni:
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"
}
}
}}
])
Ciò darebbe invece un output come questo:
{
"_id": "item_1"
"results":[
{ "rating": "good", "count": 12 },
{ "rating": "neutral", "count": 10 }
{ "rating": "bad", "count": 67 }
]
}
Sono tutte le stesse informazioni, ma non dovevi far corrispondere esplicitamente i valori e in questo modo viene eseguito molto più velocemente.