Обновление MongoDB (конвейер агрегации) с использованием значений из вложенных вложенных массивов - PullRequest
0 голосов
/ 14 июля 2020

Я пытаюсь обновить поле (totalPrice) в моем документе (ах) на основе значения во вложенном, вложенном массиве (addOns> получить соответствующий массив из x числа массивов> получить int в соответствующем массиве [всегда в pos 2]).

Вот пример документа с двумя массивами, вложенными в надстройки:

{
   "_id": ObjectID('.....'),
   "addOns": [
                ["appleId", "Apples", 2],
                ["bananaID", "Bananas", 1]
             ],
   "totalPrice": 5.7
}

Допустим, цена бананов увеличилась на 20 центов, поэтому мне нужно искать все документы, в дополнении которых есть бананы, а затем увеличить общую стоимость этих документов в зависимости от количества купленных бананов. Я планирую использовать запрос updateMany () с конвейером агрегирования, который должен примерно выглядеть как в примере ниже. ??? должно быть количество купленных бананов, но я не знаю, как go получить это значение. До сих пор я думал об использовании $ unwind, $ filter и $ arrayElemAt, но не знаю, как использовать их вместе. Был бы признателен за любую помощь!

db.collection('orders').updateMany(
     { $elemMatch: { $elemMatch: { $in: ['bananaID'] } } },
     [
          { $set: {'totalPrice': { $add: ['$totalPrice', { $multiply: [{$toDecimal: '0.2'}, ???] } ] } } }
     ]

Я не совсем уверен, какая у меня версия mon go, но я знаю, что могу использовать конвейер агрегации, потому что у меня есть другие вызовы updateMany (), которые также используйте конвейер без каких-либо проблем, поэтому он должен быть (версия> = 4.2).

** Edit : подумал об этом для ???, шаг фильтра, похоже, работает несколько поскольку документы обновляются, но вместо обновленной цены значение равно нулю. Не уверен, почему

  1. Отфильтруйте массив '$ addOns', чтобы вернуть соответствующий вложенный массив.
  2. В качестве условия используйте $ eq, чтобы проверить, находится ли элемент в [0] (' $$ this.0 ') соответствует строке' bananaID ', и если она возвращает этот вложенный массив.
  3. Получить массив, возвращенный с шага 1, используя $ arrayElemAt и позицию [0].
  4. Снова используйте $ arrayElemAt в массиве из шага 3 с positon [2], поскольку это индекс элемента количества
{ $arrayElemAt: [{ $arrayElemAt: [ { $filter: { input: "$addOns", as:'this', cond: { $eq: ['$$this.0', 'bananaID'] } } } , 0 ] }, 2 ] }

1 Ответ

0 голосов
/ 15 июля 2020

Удалось решить эту проблему самому - хотя используйте это только в том случае, если вы не возражаете против риска updateMany (), как указано Джо в комментариях к вопросу. Это очень похоже на то, что я изначально использовал в ** Edit , за исключением того, что вы не можете использовать $$this.0 для доступа к элементам в массиве.

Вставьте это туда, где ??? есть, и он будет работать, под этим блоком кода находится объяснение:

{ $arrayElemAt: [{ $arrayElemAt: [ { $filter: { input: "$addOns", as:'this', cond: { $eq: [{$arrayElemAt:['$$this', 0]}, 'bananaID'] } } } , 0 ] }, 2 ] }
  1. Наш массив выглядит следующим образом: [["appleId", "Apples", 2], ["bananaID", "Bananas", 1]]
  2. Используйте $ filter, чтобы вернуть подмножество наш массив, содержащий только элементы, соответствующие нашему условию - в данном случае нам нужен массив для бананов. $$this представляет каждый элемент на входе, и мы проверяем, соответствует ли первый элемент $$this bananaID.
{ $filter: { input: "$addOns", as:'this', cond: { $eq: [{$arrayElemAt:['$$this', 0]}, 'bananaID'] } } }

// how the result from $filter should look like
// [["bananaID", "Bananas", 1]]
Поскольку вложенный банановый массив всегда будет первым элементом, мы используем $ arrayElemAt для результата шага 2, чтобы получить элемент в позиции 0.
// How it looks like after step 3: ["bananaID", "Bananas", 1]
Последний шаг - снова использовать $ arrayElemAt, за исключением того, что на этот раз мы хотим получить элемент в позиции 2 (количество купленных бананов) Вот как выглядит окончательный запрос updateMany () после шагов Оцениваются 1-4.
db.collection('orders').updateMany(
     { $elemMatch: { $elemMatch: { $in: ['bananaID'] } } },
     [
          { $set: {'totalPrice': { $add: ['$totalPrice', { $multiply: [{$toDecimal: '0.2'}, 1] } ] } } }
     ], *callback function code*)

// notice how the ??? is now replaced by the quantity of bananas which is 1
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...