MongoDB
 sql >> Base de données >  >> NoSQL >> MongoDB

MongoDB :Combien y a-t-il de valeurs distinctes ?

Vous étiez très proche, mais bien sûr $eq renvoie juste un true/false valeur, donc pour rendre ce numérique, vous avez besoin de $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 ]
           }
       }
  }}
])

En tant qu'opérateur "ternaire" $cond prend une condition logique comme premier argument (if) puis renvoie le deuxième argument où l'évaluation est true (alors) ou le troisième argument où false (autre). Cela rend true/false retourne en 1 et 0 pour alimenter $sum respectivement.

Notez également que la "casse" est sensible pour $eq . Si vous avez des cas variables, vous voudrez probablement $toLower dans les expressions :

               "$cond": [ { "$eq": [ { "$toLower": "$rating" },  "bad" ] }, 1, 0 ]

Sur une note légèrement différente, l'agrégation suivante est généralement plus flexible pour différentes valeurs possibles et tourne autour des sommes conditionnelles en termes de performances :

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"
            }
        }
    }}
])

Cela donnerait plutôt une sortie comme celle-ci :

{
    "_id": "item_1"
    "results":[
        { "rating": "good", "count": 12 },
        { "rating": "neutral", "count": 10 }
        { "rating": "bad", "count": 67 }
    ]
}

Ce sont toutes les mêmes informations, mais vous n'avez pas eu à faire correspondre explicitement les valeurs et cela s'exécute beaucoup plus rapidement de cette façon.