db.collection.bulkWrite()

在本页面

Definition

  • db.collection. bulkWrite ( )
    • 3.2 版中的新功能。

使用控件执行多个写入操作以执行 Sequences。

bulkWrite()具有以下语法:

db.collection.bulkWrite(
   [ <operation 1>, <operation 2>, ... ],
   {
      writeConcern : <document>,
      ordered : <boolean>
   }
)
ParameterTypeDescription
operationsarraybulkWrite()个写操作的数组。


有效操作是:
insertOne
updateOne
updateMany
deleteOne
deleteMany
replaceOne
有关每个操作的用法,请参见Write Operations
| writeConcern |文档|可选。表示write concern的文档。忽略使用默认的写关注。
| ordered |布尔值|可选。一个布尔值,指定mongod实例应执行有序操作还是无序操作执行。默认为true
See 执行作业|

返回:如果操作以write concernfalse运行,则布尔acknowledged作为true,如果禁用了写关注,则为_3.
每个写入操作的计数。
一个数组,其中包含每个成功插入或升级后的文档的_id

Behavior

bulkWrite()接受一系列写操作并执行每个操作。默认情况下,操作按 Sequences 执行。有关控制写入操作执行 Sequences 的信息,请参见执行作业

Write Operations

insertOne

将单个文档插入集合中。

See db.collection.insertOne().

db.collection.bulkWrite( [
   { insertOne : { "document" : <document> } }
] )

updateOne 和 updateMany

在版本 3.6 中更改:updateOneupdateMany操作增加了对arrayFilters参数的支持,该参数确定要在数组字段中修改的元素。有关详细信息,请参考db.collection.updateOne()db.collection.updateMany()

在版本 3.4 中进行了更改:添加了对collation的支持。有关详情,请参见db.collection.updateOne()db.collection.updateMany()

updateOne更新集合中与过滤器匹配的单个文档。如果有多个文档匹配,updateOne将仅更新* first *匹配的文档。参见db.collection.updateOne()

db.collection.bulkWrite( [
   { updateOne :
      {
         "filter" : <document>,
         "update" : <document>,
         "upsert" : <boolean>,
         "collation": <document>,
         "arrayFilters": [ <filterdocument1>, ... ]
      }
   }
] )

updateMany更新集合中与过滤器匹配的所有文档。参见db.collection.updateMany()

db.collection.bulkWrite( [
   { updateMany :
      {
         "filter" : <document>,
         "update" : <document>,
         "upsert" : <boolean>,
         "collation": <document>,
         "arrayFilters": [ <filterdocument1>, ... ]
      }
   }
] )

query selectors(例如与find()一起使用的__)用于filter字段。

update字段中使用Update Operators,例如$set$unset$rename

默认情况下,upsertfalse

replaceOne

在版本 3.4 中进行了更改:添加了对collation的支持。详情请参阅db.collection.replaceOne()

replaceOne替换集合中与过滤器匹配的**文档。如果多个文档匹配,则replaceOne将仅替换 first *匹配的文档。参见db.collection.replaceOne()

db.collection.bulkWrite([
   { replaceOne :
      {
         "filter" : <document>,
         "replacement" : <document>,
         "upsert" : <boolean>
      }
   }
] )

query selectors(例如与find()一起使用的__)用于filter字段。

replacement字段不能包含update operators

默认情况下,upsertfalse

删除一个并删除许多

在版本 3.4 中进行了更改:添加了对collation的支持。有关详情,请参见db.collection.deleteOne()db.collection.deleteMany()

deleteOne删除集合中与过滤器匹配的单个文档。如果多个文档匹配,deleteOne将仅删除* first *匹配的文档。参见db.collection.deleteOne()

db.collection.bulkWrite([
   { deleteOne :  { "filter" : <document> } }
] )

deleteMany删除集合中与过滤器匹配的所有文档。参见db.collection.deleteMany()

db.collection.bulkWrite([
   { deleteMany :  { "filter" : <document> } }
] )

query selectors(例如与find()一起使用的__)用于filter字段。

_id Field

如果文档未指定_id字段,则mongod将添加_id字段并为文档分配唯一的ObjectId,然后再插入或向上插入它。大多数驱动程序会创建一个 ObjectId 并插入_id字段,但如果驱动程序或应用程序未创建,则mongod将创建并填充_id

如果文档包含_id字段,则_id值在集合中必须唯一,以避免重复的键错误。

更新或替换操作不能指定与原始文档不同的_id值。

执行作业

ordered参数指定bulkWrite()是否按 Sequences 执行操作。默认情况下,操作按 Sequences 执行。

以下代码代表具有五个操作的bulkWrite()

db.collection.bulkWrite(
   [
      { insertOne : <document> },
      { updateOne : <document> },
      { updateMany : <document> },
      { replaceOne : <document> },
      { deleteOne : <document> },
      { deleteMany : <document> }
   ]
)

在默认的ordered : true状态下,将从第一个操作insertOne到最后一个操作deleteMany依次执行每个操作。

如果ordered设置为 false,则mongod可以将操作重新排序以提高性能。应用程序不应依赖于操作执行的 Sequences。

以下代码表示具有六个操作的无序bulkWrite()

db.collection.bulkWrite(
   [
      { insertOne : <document> },
      { updateOne : <document> },
      { updateMany : <document> },
      { replaceOne : <document> },
      { deleteOne : <document> },
      { deleteMany : <document> }
   ],
   { ordered : false }
)

使用ordered : false,操作结果可能会有所不同。例如,根据在insertOneupdateOneupdateManyreplaceOne操作之前还是之后运行,deleteOnedeleteMany可能会删除更多或更少的文档。

每个组中的操作数不能超过数据库的maxWriteBatchSize的值。从 MongoDB 3.6 开始,此值为100,000。此值显示在isMaster.maxWriteBatchSize字段中。

此限制可防止出现错误消息过多的问题。如果组超过此limit,则 Client 端驱动程序会将组划分为计数小于或等于限制值的较小组。例如,使用100,000maxWriteBatchSize值,如果队列包含200,000个操作,则驱动程序将创建 2 个组,每个组具有100,000个操作。

Note

当使用高级 API 时,驱动程序仅将组划分为较小的组。如果直接使用db.runCommand()(例如,在编写驱动程序时),则 MongoDB 在尝试执行超出限制的写批处理时会引发错误。

从 MongoDB 3.6 开始,一旦单个批次的错误报告变得太大,MongoDB 就会将所有剩余的错误消息截断为空字符串。当前,至少在总大小大于1MB的 2 条错误消息后开始。

大小和分组机制是内部性能的详细信息,将来可能会更改。

在分片集合上执行ordered操作列表通常比执行unordered列表要慢,因为使用有序列表,每个操作必须 await 上一个操作完成。

Capped Collections

当在capped collection上使用bulkWrite()时,写入操作会受到限制。

如果update标准增加了要修改的文档的大小,则updateOneupdateMany抛出WriteError

如果replacement文档的大小比原始文档大,则replaceOne抛出WriteError

如果用于上限集合,则deleteOnedeleteMany抛出WriteError

Error Handling

bulkWrite()引发BulkWriteError错误。

Write Concern个错误外,有序操作在发生错误后停止,而无序操作 continue 处理队列中所有剩余的写操作。

写关注错误显示在writeConcernErrors字段中,而所有其他错误显示在writeErrors字段中。如果遇到错误,将显示成功写入操作的次数,而不是插入的_id值。有序操作显示遇到的单个错误,而无序操作显示数组中的每个错误。

Examples

批量写入操作

guidebook数据库中的characters集合包含以下文档:

{ "_id" : 1, "char" : "Brisbane", "class" : "monk", "lvl" : 4 },
{ "_id" : 2, "char" : "Eldon", "class" : "alchemist", "lvl" : 3 },
{ "_id" : 3, "char" : "Meldane", "class" : "ranger", "lvl" : 3 }

以下bulkWrite()对集合执行多项操作:

try {
   db.characters.bulkWrite([
      { insertOne: { "document": { "_id": 4, "char": "Dithras", "class": "barbarian", "lvl": 4 } } },
      { insertOne: { "document": { "_id": 5, "char": "Taeln", "class": "fighter", "lvl": 3 } } },
      { updateOne : {
         "filter" : { "char" : "Eldon" },
         "update" : { $set : { "status" : "Critical Injury" } }
      } },
      { deleteOne : { "filter" : { "char" : "Brisbane"} } },
      { replaceOne : {
         "filter" : { "char" : "Meldane" },
         "replacement" : { "char" : "Tanys", "class" : "oracle", "lvl": 4 }
      } }
   ]);
} catch (e) {
   print(e);
}

该操作返回以下内容:

{
   "acknowledged" : true,
   "deletedCount" : 1,
   "insertedCount" : 2,
   "matchedCount" : 2,
   "upsertedCount" : 0,
   "insertedIds" : {
      "0" : 4,
      "1" : 5
   },
   "upsertedIds" : {

   }
}

如果集合在执行批量写入之前包含带有"_id" : 5"的文档,则在执行批量写入时,将为第二个 insertOne 抛出以下重复键异常:

BulkWriteError({
   "writeErrors" : [
      {
         "index" : 1,
         "code" : 11000,
         "errmsg" : "E11000 duplicate key error collection: guidebook.characters index: _id_ dup key: { : 5.0 }",
         "op" : {
            "_id" : 5,
            "char" : "Taeln",
            "class" : "fighter",
            "lvl" : 3
         }
      }
   ],
   "writeConcernErrors" : [ ],
   "nInserted" : 1,
   "nUpserted" : 0,
   "nMatched" : 0,
   "nModified" : 0,
   "nRemoved" : 0,
   "upserted" : [ ]
})

由于ordered默认为 true,因此仅第一个操作成功完成。其余的不执行。使用ordered : false运行bulkWrite()将允许其余操作完成,尽管出现错误。

无序批量写入

guidebook数据库中的characters集合包含以下文档:

{ "_id" : 1, "char" : "Brisbane", "class" : "monk", "lvl" : 4 },
{ "_id" : 2, "char" : "Eldon", "class" : "alchemist", "lvl" : 3 },
{ "_id" : 3, "char" : "Meldane", "class" : "ranger", "lvl" : 3 }

以下bulkWrite()characters集合执行多个unordered操作。请注意,insertOne阶段之一具有重复的_id值:

try {
   db.characters.bulkWrite([
      { insertOne: { "document": { "_id": 4, "char": "Dithras", "class": "barbarian", "lvl": 4 } } },
      { insertOne: { "document": { "_id": 4, "char": "Taeln", "class": "fighter", "lvl": 3 } } },
      { updateOne : {
         "filter" : { "char" : "Eldon" },
         "update" : { $set : { "status" : "Critical Injury" } }
      } },
      { deleteOne : { "filter" : { "char" : "Brisbane"} } },
      { replaceOne : {
         "filter" : { "char" : "Meldane" },
         "replacement" : { "char" : "Tanys", "class" : "oracle", "lvl": 4 }
      } }
   ], { ordered : false } );
} catch (e) {
   print(e);
}

该操作返回以下内容:

BulkWriteError({
   "writeErrors" : [
      {
         "index" : 1,
         "code" : 11000,
         "errmsg" : "E11000 duplicate key error collection: guidebook.characters index: _id_ dup key: { : 4.0 }",
         "op" : {
            "_id" : 4,
            "char" : "Taeln",
            "class" : "fighter",
            "lvl" : 3
         }
      }
   ],
   "writeConcernErrors" : [ ],
   "nInserted" : 1,
   "nUpserted" : 0,
   "nMatched" : 2,
   "nModified" : 2,
   "nRemoved" : 1,
   "upserted" : [ ]
})

由于这是unordered操作,因此尽管有异常,但仍处理了队列中剩余的写入。

具有写问题的批量写

enemies集合包含以下文档:

{ "_id" : 1, "char" : "goblin", "rating" : 1, "encounter" : 0.24 },
{ "_id" : 2, "char" : "hobgoblin", "rating" : 1.5, "encounter" : 0.30 },
{ "_id" : 3, "char" : "ogre", "rating" : 3, "encounter" : 0.2 },
{ "_id" : 4, "char" : "ogre berserker" , "rating" : 3.5, "encounter" : 0.12}

以下bulkWrite()使用"majority"write concern值和 100 毫秒的timeout值对集合执行多项操作:

try {
   db.enemies.bulkWrite(
      [
         { updateMany :
            {
               "filter" : { "rating" : { $gte : 3} },
               "update" : { $inc : { "encounter" : 0.1 } }
            },

         },
         { updateMany :
            {
               "filter" : { "rating" : { $lt : 2} },
               "update" : { $inc : { "encounter" : -0.25 } }
            },
         },
         { deleteMany : { "filter" : { "encounter": { $lt : 0 } } } },
         { insertOne :
            {
               "document" :
                  {
                     "_id" :5, "char" : "ogrekin" , "rating" : 2, "encounter" : 0.31
                  }
            }
         }
      ],
      { writeConcern : { w : "majority", wtimeout : 100 } }
   );
} catch (e) {
   print(e);
}

如果副本集中所有必需节点确认写操作所需的总时间大于wtimeout,则经过wtimeout周期后,将显示以下writeConcernError

BulkWriteError({
   "writeErrors" : [ ],
   "writeConcernErrors" : [
      {
         "code" : 64,
         "codeName" : "WriteConcernFailed",
         "errInfo" : {
            "wtimeout" : true
         },
         "errmsg" : "waiting for replication timed out"
      },
      {
         "code" : 64,
         "codeName" : "WriteConcernFailed",
         "errInfo" : {
            "wtimeout" : true
         },
         "errmsg" : "waiting for replication timed out"
      },
      {
         "code" : 64,
         "codeName" : "WriteConcernFailed",
         "errInfo" : {
            "wtimeout" : true
         },
         "errmsg" : "waiting for replication timed out"
      }
   ],
   "nInserted" : 1,
   "nUpserted" : 0,
   "nMatched" : 4,
   "nModified" : 4,
   "nRemoved" : 1,
   "upserted" : [ ]
})

结果集显示执行的操作,因为writeConcernErrors错误不是*任何写入操作失败的指示。