MongoDB
 sql >> Base de Dados >  >> NoSQL >> MongoDB

Chaves dinâmicas após $group by


Não que eu ache que seja uma boa ideia e principalmente porque eu não vejo nenhuma "agregação" aqui é que depois de "agrupar" para adicionar a um array você similarmente $push todo esse conteúdo em array pelo "status" chave de agrupamento e, em seguida, converta em chaves de um documento em um $replaceRoot com $arrayToObject :
db.collection.aggregate([
  { "$group": {
    "_id": "$status",
    "data": { "$push": "$$ROOT" }
  }},
  { "$group": {
    "_id": null,
    "data": {
      "$push": {
        "k": "$_id",
        "v": "$data"
      }
    }
  }},
  { "$replaceRoot": {
    "newRoot": { "$arrayToObject": "$data" }
  }}
])

Devoluções:
{
        "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..."
                }
        ]
}

Isso pode ser bom SE você realmente "agregou" de antemão, mas em qualquer coleção de tamanho prático, tudo o que está fazendo é tentar forçar toda a coleção em um único documento, e isso provavelmente quebrará o limite BSON de 16 MB, então eu não recomendaria nem tentar isso sem " agrupamento" outra coisa antes desta etapa.

Francamente, o mesmo código a seguir faz a mesma coisa e sem truques de agregação e sem problema de limite 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);

Ou um pouco mais curto:
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);

As agregações são usadas para "redução de dados" e qualquer coisa que seja simplesmente "reformando resultados" sem realmente reduzir os dados retornados do servidor geralmente é melhor tratada no código do cliente de qualquer maneira. Você ainda está retornando todos os dados, não importa o que você faça, e o processamento do cursor pelo cliente tem uma sobrecarga consideravelmente menor. E SEM restrições.