sql >> Base de Datos >  >> NoSQL >> MongoDB

Claves dinámicas después de $group by

No es que piense que es una buena idea y principalmente porque no veo ninguna "agregación" aquí en absoluto es que después de "agrupar" para agregar a una matriz, de manera similar $push todo ese contenido en una matriz por el "status" clave de agrupación y luego convertir en claves de un documento en un $replaceRoot con $arrayToObject :

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

Devoluciones:

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

Eso podría estar bien SI en realidad "agregó" de antemano, pero en cualquier colección de tamaño práctico, todo lo que está haciendo es intentar forzar toda la colección en un solo documento, y es probable que rompa el límite de BSON de 16 MB, por lo que simplemente no recomendaría intentar esto sin " agrupando" algo más antes de este paso.

Francamente, el mismo código siguiente hace lo mismo, y sin trucos de agregación ni problema de límite de BSON:

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

O un poco más corto:

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

Las agregaciones se utilizan para la "reducción de datos" y cualquier cosa que sea simplemente "remodelar los resultados" sin reducir realmente los datos devueltos por el servidor generalmente se maneja mejor en el código del cliente de todos modos. Todavía está devolviendo todos los datos sin importar lo que haga, y el procesamiento del cursor por parte del cliente tiene una sobrecarga considerablemente menor. Y SIN restricciones.