sql >> Databasteknik >  >> NoSQL >> MongoDB

Räkna distinkta underdokumentfält och utdata som namngivna nycklar

Grundfallet här är att använda .aggregate() med $unwind eftersom du behöver tillgång till värdena i arrayen som dina grupperingsnycklar och naturligtvis $group eftersom det är så man "grupperar" saker:

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

Detta ger dig utdata som:

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

Nu borde du verkligen lära dig att leva med det, för en "lista" i standardmarkörformatet är en bra sak som är naturligt iterabel. Inte heller IMHO-namngivna nycklar lämpar sig naturligt för datapresentation och du vill vanligtvis ha en gemensam egenskap i en iterabel lista.

Om du verkligen är sugen på att använda singularnamnet nycklar, kommer du antingen att behöva MongoDB 3.4.4 eller senare för att ha tillgång till $arrayToObject som gör att du kan använda värdena som namn på nycklar, och naturligtvis $replaceRoot för att använda det uttrycket som det nya dokumentet att producera:

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

Eller om du inte har det alternativet, då bör du istället konvertera markörens utdata till kod:

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

Båda slås samman till ett enda objekt med namngivna nycklar från den ursprungliga aggregeringsutgången:

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

Och det visar att det ursprungliga resultatet verkligen var tillräckligt, och att du vanligtvis vill att den typen av "slutlig omformning" ska göras i koden som använder markörutgången, om du verkligen ens behöver den omformningen överhuvudtaget eftersom den grundläggande data som behövs returnerades ändå.



  1. PyMongo -- marköriteration

  2. MongoDB - Hur man hittar distinkta värden baserat på delsträng

  3. mongodb-fel vid validering av inställningar:endast ett positionsargument är tillåtet

  4. Hur vet man master/slav status för redis?