MongoDB Aggregation: добавьте каждое значение массива к каждому объекту в массиве из другого поля. Объединить / объединить два массива из разных полей - PullRequest
1 голос
/ 13 апреля 2020

Я нахожусь в середине сложного запроса агрегации (с поиском и многими этапами групп / раскрутки) и сталкиваюсь с проблемой объединения двух разных массивов из разных полей.

Как сейчас, после одного из этапов ( в середине или после поиска моего большого запроса) У меня есть следующий вывод:

{
  _id: 1,
  quantity: [2, 1, 3]
  reagents: [ 
     {name: "FirstItem", other_field: ... },
     {name: "SecondItem", other_field: ... },
     {name: "ThirdItem", other_field: ... }
  ]
}

И я хочу:

  _id: 1,
  reagents: [ 
     {name: "FirstItem", quantity: 2 },
     {name: "SecondItem", quantity: 1 },
     {name: "ThirdItem", quantity: 3 }
  ]

Таким образом, каждое значение [quantity], которое я хочу добавить каждый объект внутри [reagents] как поле в соответствии с его индексом, например, первый {object} внутри reagents должен иметь первую element из [quantity]

схему с индексами массива):

quantity: [2, 1, 3, ... n]
           ↓  ↓  ↓      ↓
reagents: [1, 2, 3, ... n]

ПРОБЛЕМА:

Я не могу сделать это после или до агрегации, потому что:

  • У меня нет необходимых данных, причина это результат поиска из разных коллекций.

  • Я не могу сделать это после, потому что сразу после этого я должен $group данные по другому полю, поэтому [reagents] порядок сортировки был потерян и не может быть восстановлено.

UPD : * 1 040 * Я понимаю, что мог (и, вероятно, должен использовать $unwind stage для [reagents], но я не нашел каких-либо соответствующих операторов этапа агрегации в Mon go Manual . Так что, если вы знаете нужный, пожалуйста, укажите мне.

Ответы [ 2 ]

1 голос
/ 13 апреля 2020

@ Ответ Аша будет работать идеально (а афаик - лучшее решение), если вам не нужно оставлять в результатах другие поля, кроме имени и количества. Но если вам нужно сохранить их, вам придется добавлять каждое поле вручную, что иногда бывает утомительно. Существует еще одно «общее» решение для решения этого случая с оператором $ zip , который предназначен для объединения массивов по индексу.

db.collection.aggregate([
  {
    $addFields: {
      reagents: {
        $map: {
          input: {
            $zip: {
              inputs: [
                "$quantity",
                "$reagents"
              ]
            }
          },
          as: "reagent",
          in: {
            $mergeObjects: [
              {
                $arrayElemAt: [
                  "$$reagent",
                  1
                ]
              },
              {
                quantity: {
                  $arrayElemAt: [
                    "$$reagent",
                    0
                  ]
                }
              }
            ]
          }
        }
      }
    }
  }
])

Пн go детская площадка

1 голос
/ 13 апреля 2020

Вы можете добавить ниже уровня

 { "$addFields": {
   "reagents": {
     "$map": {
       "input": { "$range": [0, { "$size": "$reagents" }] },
       "in": {
         "name": {
           "$arrayElemAt": ["$reagents.name", "$$this"]
         },
         "quantity": {
           "$arrayElemAt": ["$quantity", "$$this"]
         }
       }
     }
   }
 }}

MongoPlayground

...