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

Compter le champ de sous-document distinct et la sortie en tant que clés nommées

Le cas de base ici est d'utiliser .aggregate() avec $unwind car vous avez besoin d'accéder aux valeurs du tableau en tant que clés de regroupement et bien sûr $group car c'est ainsi que vous "regroupez" les choses :

db.collection.aggregate([
  { "$match": { "auctionId": 22 } },
  { "$unwind": "$itmLst" },
  { "$group": {
    "_id": "$itmLst.category",
    "count": { "$sum": 1 }
  }}
])

Cela vous donnera une sortie comme :

{ "_id": "ANTIQUES", "count": 56 }
{ "_id": "TOOLS", "count": 89 }
{ "_id": "JEWLRY", "count":  45 }

Maintenant, vous devriez vraiment apprendre à vivre avec cela, car une "liste" dans le format de curseur par défaut est une bonne chose qui est naturellement itérable. De plus, les clés nommées à mon humble avis ne se prêtent pas naturellement à la présentation des données et vous souhaitez généralement une propriété commune dans une liste itérable.

Si vous avez vraiment l'intention d'utiliser la sortie des clés nommées singulières, vous aurez besoin de MongoDB 3.4.4 ou supérieur pour avoir accès à $arrayToObject qui vous permettra d'utiliser les valeurs comme noms de clés, et bien sûr $replaceRoot afin d'utiliser cette sortie d'expression comme nouveau document à produire :

db.collection.aggregate([
  { "$match": { "auctionId": 22 } },
  { "$unwind": "$itmLst" },
  { "$group": {
    "_id": "$itmLst.category",
    "count": { "$sum": 1 }
  }},
  { "$group": {
    "_id": null,
    "data": { "$push": { "k": "$_id", "v": "$count" } }
  }},
  { "$replaceRoot": {
    "newRoot": {
      "$arrayToObject": "$data"
    }
  }}
])

Ou si vous n'avez pas cette option, vous devriez plutôt convertir la sortie du curseur en code :

db.collection.aggregate([
  { "$match": { "auctionId": 22 } },
  { "$unwind": "$itmLst" },
  { "$group": {
    "_id": "$itmLst.category",
    "count": { "$sum": 1 }
  }}
]).toArray().reduce((acc,curr) => 
  Object.assign(acc,{ [curr._id]: curr.count }),
  {}
)

Les deux fusionnent en un seul objet avec des clés nommées à partir de la sortie d'agrégation d'origine :

{
    "ANTIQUES": 56,
    "TOOLS": 89,
    "JEWLRY": 45,
    ...
}

Et cela montre que le résultat de sortie d'origine était vraiment suffisant, et que vous voulez généralement que ce type de "remodelage final" soit effectué dans le code qui utilise la sortie du curseur, si vous avez vraiment besoin de ce remodelage du tout depuis la base les données nécessaires ont quand même été renvoyées.