MongoDB
 sql >> Datenbank >  >> NoSQL >> MongoDB

Dynamische Schlüssel nach $group by

Nicht, dass ich es für eine gute Idee halte, und vor allem, weil ich hier überhaupt keine "Aggregation" sehe, ist es so, dass Sie nach dem "Gruppieren", um es zu einem Array hinzuzufügen, auf ähnliche Weise $push all dieser Inhalt in ein Array durch den "status" Gruppierungsschlüssel und dann in Schlüssel eines Dokuments in einem $replaceRoot konvertieren mit $arrayToObject :

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

Rückgabe:

{
        "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..."
                }
        ]
}

Das könnte in Ordnung sein IF Sie haben tatsächlich vorher "aggregiert", aber bei jeder praktisch großen Sammlung versucht man nur, die gesamte Sammlung in ein einziges Dokument zu zwingen, und das wird wahrscheinlich die BSON-Grenze von 16 MB überschreiten, daher würde ich nicht empfehlen, dies auch nur zu versuchen ohne " Gruppieren" etwas anderes vor diesem Schritt.

Ehrlich gesagt macht derselbe folgende Code dasselbe, und zwar ohne Aggregationstricks und ohne BSON-Limit-Problem:

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);

Oder etwas kürzer:

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);

Aggregationen werden zur "Datenreduktion" verwendet, und alles, was einfach nur "Ergebnisse umgestaltet", ohne die vom Server zurückgegebenen Daten tatsächlich zu reduzieren, wird normalerweise sowieso besser im Client-Code gehandhabt. Sie geben immer noch alle Daten zurück, egal was Sie tun, und die Client-Verarbeitung des Cursors hat erheblich weniger Overhead. Und KEINE Beschränkungen.