MongoDB — arrayFilters и updateMany из одного документа

У меня есть следующий образец данных:

{
  _id: 1,
  seniorityDate: '2001-01-01T00:00:00Z',
  assigned: [
    {
      groupId: 11,
      system: 'Dep',
      effectiveDate: null
    },
    {
      groupId: 12,
      system: 'Team',
      effectiveDate: null
    },
    ...
  ]
}

и я хотел бы обновить объект effectiveDate на основе seniorityDate в массиве assigned, где только system:'Team':

db.collection.updateMany({}, 
[{
    $set: {
        'assigned.$[elem].effectiveDate': '$seniorityDate'
    }
}], {
    arrayFilters: [{
        "elem.system": "Team"
    }]
})

но я получил следующую ошибку:

arrayFilters не может быть указан для конвейерных обновлений.


Ожидаемый результат будет:

{
  _id: 1,
  seniorityDate: '2001-01-01T00:00:00Z',
  assigned: [
    {
      groupId: 11,
      system: 'Dep',
      effectiveDate: null
    },
    {
      groupId: 12,
      system: 'Team',
      effectiveDate: '2001-01-01T00:00:00Z'
    },
    ...
  ]
}

Как я могу достичь этого?

Использование JavaScript и MongoDB
Использование JavaScript и MongoDB
Сегодня я собираюсь вкратце рассказать о прототипах в JavaScript, а также представить и объяснить вам работу с базой данных MongoDB.
1
0
58
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

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

  1. $set - установить поле assigned.

    1.1. $map — перебрать элемент в массиве assigned и вернуть новый массив.

    1.1.1. $mergeObjects - объединить текущий повторный документ с документом из 1.1.1.1.

    1.1.1.1. Документ с полем effectiveDate. С оператором $cond, если соответствует условию, используйте значение seniorityDate, в противном случае сохраните существующее значение.

db.collection.updateMany({},
[
  {
    $set: {
      "assigned": {
        $map: {
          input: "$assigned",
          in: {
            $mergeObjects: [
              "$$this",
              {
                effectiveDate: {
                  $cond: {
                    if: {
                      $eq: [
                        "$$this.system",
                        "Team"
                      ]
                    },
                    then: "$seniorityDate",
                    else: "$$this.effectiveDate"
                  }
                }
              }
            ]
          }
        }
      }
    }
  }
])

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

Следовательно, ваш запрос на обновление с условием запроса будет выглядеть следующим образом:

db.collection.updateMany({
  "assigned.system": "Team"
},
[
  ...
])

Демонстрация @ Mongo Playground

Поскольку обновлять нужно только документы с "assigned.system": "Team", вы можете добавить это как фильтр к updateMany.

rickhg12hs 12.10.2022 05:16

Да, вы правы, ограничьте количество документов для повышения производительности запросов. Спасибо за предложение. знак равно

Yong Shun 12.10.2022 05:17

Спасибо, @rickhg12hs за ваше действительное предложение.

Mehran Ishanian 12.10.2022 17:50

Другие вопросы по теме