Je was heel dichtbij, maar natuurlijk $eq retourneert gewoon een true/false waarde, dus om die numerieke waarde te maken heb je $cond . nodig :
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 ]
}
}
}}
])
Als een "ternaire" operator $cond neemt een logische voorwaarde als eerste argument (if) en retourneert vervolgens het tweede argument waarbij de evaluatie true is (then) of het derde argument waarbij false (anders). Dit maakt true/false keert terug naar 1 en 0 om door te geven aan $sum respectievelijk.
Merk ook op dat "case" gevoelig is voor $eq . Als je verschillende hoofdletters hebt, wil je waarschijnlijk $toLower in de uitdrukkingen:
"$cond": [ { "$eq": [ { "$toLower": "$rating" }, "bad" ] }, 1, 0 ]
Met een iets andere opmerking, de volgende aggregatie is meestal flexibeler voor verschillende mogelijke waarden en draait rond de voorwaardelijke sommen in termen van prestaties:
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"
}
}
}}
])
Dat zou in plaats daarvan de volgende output opleveren:
{
"_id": "item_1"
"results":[
{ "rating": "good", "count": 12 },
{ "rating": "neutral", "count": 10 }
{ "rating": "bad", "count": 67 }
]
}
Het is allemaal dezelfde informatie, maar je hoefde de waarden niet expliciet te matchen en het wordt op deze manier veel sneller uitgevoerd.