Динамические клавиши после $ group by - PullRequest
0 голосов
/ 07 июня 2018

У меня есть следующая коллекция

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

Мне нужно сгруппировать по status и динамически получить все ключи, которые находятся в status

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

1 Ответ

0 голосов
/ 07 июня 2018

Не то, чтобы я думал, что это хорошая идея, и в основном потому, что я не вижу здесь никакой «агрегации», это то, что после «группировки» вы добавляете в массив аналогично $push все этосодержимое в массив с помощью "status" ключа группировки, а затем преобразовать в ключи документа в формате $replaceRoot с $arrayToObject:

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

Возвращает:

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

Это может быть хорошо ЕСЛИ вы на самом деле "агрегировали" заранее, но в любой практически размерной коллекции все, что делается, - это пытается собрать всю коллекцию в один документ, иэто может нарушить BSON Limit в 16 МБ , поэтому я просто не рекомендовал бы даже пытаться сделать это, не «группируя» что-то еще перед этим шагом.

Честно говоря, тот же следующий код выполняет то же самоевещь, без уловок агрегации и без ограничения 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);

Или немного короче:

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

Агрегации используются для «сокращения данных» и всего, что просто «переформирует»Результаты "Wiно фактически сокращение объема данных, возвращаемых с сервера, в любом случае обычно лучше обрабатывается в клиентском коде.Вы по-прежнему возвращаете все данные, независимо от того, что вы делаете, и клиентская обработка курсора значительно снижает накладные расходы.И никаких ограничений.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...