MongoDB
 sql >> Database >  >> NoSQL >> MongoDB

Conta il campo del documento secondario distintivo e l'output come chiavi con nome

Il caso di base qui è usare .aggregate() con $unwind perché è necessario accedere ai valori nell'array come chiavi di raggruppamento e, naturalmente, $group perché è così che "raggruppi" le cose:

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

Questo ti darà un output come:

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

Ora dovresti davvero imparare a conviverci, perché un "elenco" nel formato predefinito del cursore è una buona cosa che è naturalmente iterabile. Inoltre, le chiavi con nome IMHO non si prestano naturalmente alla presentazione dei dati e generalmente si desidera una proprietà comune in un elenco iterabile.

Se intendi davvero utilizzare l'output delle chiavi con nome singolare, avrai bisogno di MongoDB 3.4.4 o versione successiva per avere accesso a $arrayToObject che ti consentirà di utilizzare i valori come nomi di chiavi e, naturalmente, $replaceRoot per utilizzare l'output dell'espressione come nuovo documento da produrre:

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 se non hai questa opzione, dovresti invece convertire l'output del cursore nel codice:

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

Entrambi si uniscono in un unico oggetto con chiavi denominate dall'output di aggregazione originale:

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

E questo dimostra che il risultato dell'output originale era davvero sufficiente e che in genere si desidera che quel tipo di "rimodellamento finale" venga eseguito nel codice che utilizza l'output del cursore, se è davvero necessario quel rimodellamento poiché il di base i dati necessari sono stati comunque restituiti.