MongoDB在单个查询中更新多行

时间:2018-10-17 07:29:17

标签: node.js mongodb

我有一个包含以下文档的收藏集

{
   "_id" : 1,
   "item" : "item1",
   "stock" : 184
}
{
   "_id" : 2,
   "item" : "item2",
   "stock" : 330
}
{
   "_id" : 3,
   "item" : "item3",
   "stock" : 140
}

我想使用一个查询来更新此收藏集。

{
   "_id" : 1,
   "item" : "item1",
   "stock" : 80
}
{
   "_id" : 2,
   "item" : "item2",
   "stock" : 60
}
{
   "_id" : 3,
   "item" : "item3",
   "stock" : 170
}

我可以使用forEach来执行此操作,但是我必须一次更新数千条记录,这将很耗时。那么MongoDB是否具有此功能?

我们将非常感谢您的帮助。

3 个答案:

答案 0 :(得分:5)

您可以通过bulk operation在nodejs中使用Collection.initializeUnorderedBulkOp

var bulkOp = yourCollection.initializeUnorderedBulkOp();

bulkOp.find({ _id: 1 }).updateOne({ /* update document */ });
bulkOp.find({ _id: 2 }).updateOne({ /* update document */ });
// etc

bulkOp.execute();

您可以根据需要构建它,然后让数据库一次完成所有操作。

答案 1 :(得分:2)

您无法通过单个请求执行所需的更改。

您可以做的是:


数据量很小

对每个更改执行一次请求

await Promise.all(entries.map(x => model.findOneAndUpdate(...)));

拥有大量数据

使用光标按包处理数据。

const cursor = await model.find({
   _id: {
      $in: idsEntries,
   },
}).cursor().exec();

await handleCursorRead(cursor);

handleCursorRead(cursor) {
   return new Promise((resolve) => {
       cursor.eachAsync((x) => {
           x.stock = ...;

           x.save();
       }, {
          // How many items do we look at same time
          parallel: 250,
       }, () => {
          // When we are done processing all items
          resolve();
       });
   });
}

答案 2 :(得分:1)

更简洁的方式

您要使用

更新的数组
const array = [{
    "_id" : 1,
    "item" : "item1",
    "stock" : 80
}, {
    "_id" : 2,
    "item" : "item2",
    "stock" : 60
}, {
    "_id" : 3,
    "item" : "item3",
    "stock" : 170
}]

查询批量更新

Model.bulkWrite(
  array.map((data) => 
    ({
      updateOne: {
        filter: { _id: data._id },
        update: { $set: { stock: data.stock } }
      }
    })
  )
})