Уменьшите поле в mongodb, используя поле из того же документа - PullRequest
0 голосов
/ 05 мая 2020

У меня есть набор продуктов в магазине, где каждый документ - это продукт, связанный с магазином и их местонахождением, в дополнение к количеству этого продукта в этом магазине. Схема документа выглядит следующим образом:

Пример Do c:

{
    product         : 'Mobile Phone',
    store           : 'Electronics Store',
    total_quantity  : 5,
    locations       : [ { id: 'loc1', quantity: 3 }, { id: 'loc2', quantity: 2 } ]
}

Я хочу иметь возможность удалить местоположение из всех продуктов магазина с помощью идентификатор местоположения, а также обновляет общее количество.

Я знаю, что могу сделать это, получая каждый документ и обновляя его, но для этого требуются запросы, равные количеству продуктов, имеющих это местоположение. Следовательно, я думал о том, чтобы попытаться достичь этого, выполнив два запроса:

  • Запрос на обновление соответствует идентификатору местоположения и уменьшает общее количество на его основе на один go
  • Запрос на удаление, который извлекает местоположение из массива location

Проблема в том, что я не знаю, как выполнить первый шаг и возможно ли это. Любые другие предложения приветствуются.

1 Ответ

1 голос
/ 05 мая 2020

Поскольку вы можете выполнить update-with-an-aggregation-pipeline в .update() операциях, начиная с версии MongoDB> = 4.2, попробуйте следующие запросы:

Query 1: Этот запрос воссоздает поле total_quantity путем вычитания locations.quantity конкретного удаляемого элемента из существующего total_quantity. Также повторно создает массив locations без элемента, который необходимо удалить.

db.collection.updateMany({'locations.id': 'loc1'},
  [
    { $addFields: { total_quantity: { $subtract: [ "$total_quantity", { $arrayElemAt: [ "$locations.quantity", { $indexOfArray: [ "$locations.id", "loc1" ] } ] } ] } } },
    { $addFields: { locations: { $filter: { input: "$locations", cond: { $ne: [ "$$this.id", "loc1" ] } } } } }
  ]
)

Тест: Тестовый конвейер агрегирования здесь: mongoplayground

Запрос 2:

Этот запрос сначала повторно создает массив locations без элемента, который необходимо удалить, а затем выполняет итерацию по оставшемуся массиву locations.quantity, чтобы суммировать все quantity значения всех элементов в массиве locations для создания поля total_quantity.

db.collection.updateMany({'locations.id': 'loc1'},
  [
    { $addFields: { locations: { $filter: { input: "$locations", cond: { $ne: [ "$$this.id", "loc1" ] } } } } },
    { $addFields: { total_quantity: { $reduce: { input: "$locations.quantity", initialValue: 0, in: { $add: [ "$$value", "$$this" ] } } } } }
  ]
)

Тест: Тестовый конвейер агрегирования здесь: mongoplayground

Примечание: Если вы обнаружите какие-либо проблемы при выполнении этих запросов с помощью .updateMany(), попробуйте .update() с опцией { multi : true }.

...