sql >> Databasteknik >  >> NoSQL >> MongoDB

Dynamiska nycklar efter $group by

Inte för att jag tycker att det är en bra idé och mest för att jag inte ser någon "aggregering" här alls är att efter "gruppering" för att lägga till en array så $push allt innehåll i array med "status" grupperingsnyckel och konvertera sedan till nycklar för ett dokument i en $replaceRoot med $arrayToObject :

db.collection.aggregate([
  { "$group": {
    "_id": "$status",
    "data": { "$push": "$$ROOT" }
  }},
  { "$group": {
    "_id": null,
    "data": {
      "$push": {
        "k": "$_id",
        "v": "$data"
      }
    }
  }},
  { "$replaceRoot": {
    "newRoot": { "$arrayToObject": "$data" }
  }}
])

Returnerar:

{
        "inProgress" : [
                {
                        "_id" : ObjectId("5b18d31a27a37696ec8b5776"),
                        "status" : "inProgress",
                        "description" : "inProgress..."
                }
        ],
        "completed" : [
                {
                        "_id" : ObjectId("5b18d31a27a37696ec8b5773"),
                        "status" : "completed",
                        "description" : "completed..."
                }
        ],
        "pending" : [
                {
                        "_id" : ObjectId("5b18d14cbc83fd271b6a157c"),
                        "status" : "pending",
                        "description" : "You have to complete the challenge..."
                },
                {
                        "_id" : ObjectId("5b18d31a27a37696ec8b5775"),
                        "status" : "pending",
                        "description" : "pending..."
                }
        ]
}

Det kan vara okej OM du faktiskt "samlade" i förväg, men på alla praktiskt taget stora samlingar är allt som gör att försöka tvinga hela samlingen till ett enda dokument, och det kommer sannolikt att bryta BSON-gränsen på 16 MB, så jag skulle bara inte rekommendera att ens försöka detta utan " gruppera" något annat före detta steg.

Uppriktigt sagt, samma följande kod gör samma sak, och utan aggregeringstrick och inga BSON-gränsproblem:

var obj = {};

// Using forEach as a premise for representing "any" cursor iteration form
db.collection.find().forEach(d => {
  if (!obj.hasOwnProperty(d.status))
    obj[d.status] = [];
  obj[d.status].push(d);
})

printjson(obj);

Eller lite kortare:

var obj = {};

// Using forEach as a premise for representing "any" cursor iteration form
db.collection.find().forEach(d => 
  obj[d.status] = [ 
    ...(obj.hasOwnProperty(d.status)) ? obj[d.status] : [],
    d
  ]
)

printjson(obj);

Aggregeringar används för "datareduktion" och allt som helt enkelt "omformar resultat" utan att faktiskt reducera data som returneras från servern hanteras vanligtvis bättre i klientkod ändå. Du returnerar fortfarande all data oavsett vad du gör, och klientbearbetningen av markören har betydligt mindre omkostnader. Och INGA begränsningar.




  1. Använder du JSON med MongoDB?

  2. Det gick inte att starta docker mongo-bilden på Windows

  3. Finns det ett bra sätt att stödja popmedlemmar från Redis Sorted Set?

  4. 3 sätt att få veckan från en dejt i MongoDB