Как обновить значение переменной массива с помощью $ arrayFilters в Mongoose - PullRequest
1 голос
/ 19 июня 2020

Используя arrayFilters, мне нужно обновить коллекцию значениями динамического c из массива.

Это означает, что мне нужно обновить значения массива в $ in c, на основе в массиве, который предоставляется в arrayFilters.

ОБРАЗЕЦ ДОКУМЕНТА

{
  _id:'shopId',
  products:[
    _id:'productId',
    buys:[
     {
      _id:'abc',
      quantity:0
     },
     {
     _id:'def',
     quantity:2
     }
   ]
 ]
}

ОЖИДАЕМЫЙ РЕЗУЛЬТАТ

{
  _id:'shopId',
  products:[
    _id:'productId',
    buys:[
     {
      _id:'abc',
      quantity:1 //got incremented by 1
     },
     {
     _id:'def',
     quantity:5 //got incremented by 3
     }
   ]
 ]
}

Рассмотрим этот запрос ниже для того, что я пробовал

Shop.findOneAndUpdate(
    { "_id": ObjectId(shopId)},
    { $inc: { "products.$[p].buys.$[n].quantity": { $each: [1,3] } }},              
    { arrayFilters: [{ "p._id": ObjectId('productId') }, { "n._id": {$in: ["abc", "def"]} }]
)

Мне нужно, чтобы n._id: 'ab c' увеличивалось на 1 и n._id: 'def' для увеличения на 3, которые помещаются в массив ( в этом $ каждый в $ в c).

Теперь это не работает и выдает ошибку. Я попытался заменить $ each: [1,3] на $ in: [1,3], но все равно не работает.

Как я могу это сделать?

1 Ответ

2 голосов
/ 19 июня 2020

Начиная с MongoDB v4.2, это невозможно сделать с помощью arrayFilters за одну операцию.

Я предлагаю обновить их отдельно.

// Solution implemented in node.js since, you have tagged mongoose
// prepare condition data structure to use in multiple updates
const updateCondition = { "abc": 1, "def": 3 }

const updates = Object.entries(updateCondition).map(([key, value]) =>
  Shop.findOneAndUpdate(
    { _id: ObjectId(shopId)} ,
    { $inc: { "products.$[p].buys.$[n].quantity": value } }, // value will be iterated through [1, 3]       
    { arrayFilters: [{ "p._id": ObjectId(productId) }, { "n._id": key } }] // key will be iterated through ["abc", "def"]
  ).exec()
)

await Promise.all(updates).then(([resultA, resultB]) => {
  // resultA is the result of "abc" update
  // resultB is the result of "def" update
}).catch(err => {
  // handle err
})

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