【问题标题】:Insert or update many documents in MongoDB在 MongoDB 中插入或更新许多文档
【发布时间】:2017-03-07 18:49:37
【问题描述】:

有没有办法通过单个查询在 MongoDB 中插入或更新/替换多个文档?

假设以下集合:

[
    {_id: 1, text: "something"},
    {_id: 4, text: "baz"}
]

现在我想添加多个文档,其中一些文档可能已经在集合中。如果文档已经在集合中,我想更新/替换它们。例如,我想插入以下文档:

[
    {_id:1, text: "something else"},
    {_id:2, text: "foo"},
    {_id:3, text: "bar"}
]

查询应该插入带有_id 2 和3 的文档。它还应该更新/替换带有_id 1 的文档。在此过程之后,集合应如下所示:

[
    {_id:1, text: "something else"},
    {_id:2, text: "foo"},
    {_id:3, text: "bar"},
    {_id:4, text: "baz"}
]

一种方法可能是使用insertMany

db.collection.insertMany(
   [ {...}, {...}, {...} ],
   {
      ordered: false,
   }
)

如果出现重复,该查询将发出一个writeErrors,其中包含一个对象数组,其中包含未能插入的文档的索引。我可以浏览它们并更新它们。

但是这个过程很麻烦。有没有办法在 一个 查询中插入或更新/替换许多文档?

【问题讨论】:

    标签: mongodb


    【解决方案1】:

    正如here 所说,要做你需要的,你可以把这样的东西放进去

    script.js

    (* 警告:未经测试的代码)

    use YOUR_DB
    var bulk = db.collection.initializeUnorderedBulkOp();
    bulk.find( { _id : 1 } ).upsert().update( { $set: { "text": "something else" } } );
    bulk.find( { _id : 4 } ).upsert().update( { $set: { "text": "baz" } } );
    bulk.find( { _id : 99 } ).upsert().update( { $set: { "text": "mrga" } } );
    bulk.execute();
    

    并运行它

    mongo

    我不得不这样做,因为由于限制,我尝试更新/插入超过 1000 个文档的任何操作都不起作用。

    写入命令最多可以接受 1000 个操作。 mongo shell 中的 Bulk() 操作和驱动程序中的类似方法没有此限制。

    source

    【讨论】:

      【解决方案2】:

      考虑数据项如下:

      interface Item {
          id: string;         // unique key across collection
          someValue: string;
      }
      

      如果你有限制1000以下的项目,你可以像这样进行批量写入操作:

      public async insertOrUpdateBulk(items: Item[]) {
              try {
                  const bulkOperation = this._itemCollection.initializeUnorderedBulkOp();
                  for (let itemIndex = 0; itemIndex < items.length; itemIndex++) {
                      const item = items[itemIndex];
                      bulkOperation.find({ id: item.id }).upsert().update(item);
                  }
                  await bulkOperation.execute();
                  return true;
              } catch (err) {
                  console.log(err);
                  return false;
              }
          }
      

      如果你有超过限制1000的物品,你可以同时承诺:

      public async insertOrUpdate(items: Item[]) {
              try {
                  const promises: Array<Promise<UpdateWriteOpResult>> = [];
                  for (let itemIndex = 0; itemIndex < items.length; itemIndex++) {
                      const item = items[itemIndex];
                      const updatePromise = this.itemCollection.updateOne({ id: item.id }, item, { upsert: true });
                      promises.push(updatePromise);
                  }
                  await Promise.all(promises);
                  console.log('done...');
                  return true;
              } catch (err) {
                  console.log(err);
                  return false;
              }
          }
      

      【讨论】:

      • 我收到multi update only works with $ operators'
      • 我得到“多重更新也只适用于 $ 运算符”
      【解决方案3】:

      您也可以使用 bulkWrite api 在单个查询中更新或插入多个文档,这是一个示例

      var ops = []
      
      items.forEach(item => {
          ops.push(
              {
                  updateOne: {
                      filter: { _id: unique_id },
                      update: {
                          $set: { fields_to_update_if_exists },
                          $setOnInsert: { fileds_to_insert_if_does_not_exist }
                      },
                      upsert: true
                  }
              }
          )
      })
      
      db.collections('collection_name').bulkWrite(ops, { ordered: false });
      

      【讨论】:

        猜你喜欢
        • 2018-04-05
        • 2019-07-09
        • 2020-09-05
        • 2015-01-14
        • 1970-01-01
        • 1970-01-01
        • 2014-09-08
        • 1970-01-01
        • 2021-10-21
        相关资源
        最近更新 更多