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.