sql >> Base de Datos >  >> NoSQL >> MongoDB

Cuente el campo del subdocumento distinto y la salida como claves con nombre

El caso básico aquí es usar .aggregate() con $unwind porque necesita acceder a los valores de la matriz como claves de agrupación y, por supuesto, $group porque así es como "agrupas" las cosas:

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

Esto le dará una salida como:

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

Ahora realmente debería aprender a vivir con eso, porque una "lista" en el formato de cursor predeterminado es algo bueno que es naturalmente iterable. Además, en mi humilde opinión, las claves con nombre no se prestan naturalmente a la presentación de datos y, por lo general, desea una propiedad común en una lista iterable.

Si realmente tiene la intención de usar la salida de claves con nombre singular, entonces necesitará MongoDB 3.4.4 o superior para tener acceso a $arrayToObject eso le permitirá usar los valores como los nombres de las claves y, por supuesto, $replaceRoot para usar esa salida de expresión como el nuevo documento a producir:

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

O si no tiene esa opción, entonces debería convertir la salida del cursor en código:

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 }),
  {}
)

Ambos se fusionan en un solo objeto con claves nombradas de la salida de agregación original:

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

Y eso demuestra que el resultado de la salida original fue realmente suficiente y que, por lo general, desea que se realice ese tipo de "remodelación final" en el código que usa la salida del cursor, si es que realmente necesita esa remodelación desde el principio. los datos necesarios se devolvieron de todos modos.