bulkWrite
定义
8.0版本新增。
从MongoDB 8.0开始,您可以使用新的 bulkWrite
命令在一个请求中对多个集合执行多次插入、更新和删除操作。 现有的 db.collection.bulkWrite()
方法仅允许您在一个请求中修改一个集合。
要在bulkWrite
命令中指定每个集合,请使用命名空间(数据库和集合名称)。
语法
该命令的语法如下:
db.adminCommand( { bulkWrite: 1, // Include the insert, update, and delete operations // in the ops array ops: [ { insert: <integer>, // Namespace ID index for insert operation. // Must match a namespace ID index in // ns specified later in the nsInfo array. document: <document> }, { update: <integer>, // Namespace ID index for update operation filter: <document>, updateMods: <document>, arrayFilters: [ <filterDocument0>, <filterDocument1>, ... ], multi: <bolean>, hint: <document>, constants: <document>, collation: <document> }, { delete: <integer>, // Namespace ID index for delete operation filter: <document>, multi: <boolean>, hint: <document>, collation: <document> }, ... // Additional insert, update, and delete operations in any order ... ], // Include the namespaces with collections to modify // in the nsInfo array. You can add multiple namespaces here. nsInfo: [ { ns: <string>, // Namespace (database and collection name) to modify. // Each operation namespace ID index // specified in the earlier ops array must // match a namespace ID index here. collectionUUID: <string>, encryptionInformation: <document> }, ... // Additional namespaces ... ], // Additional fields ordered: <boolean>, bypassDocumentValidation: <boolean>, comment: <string>, let: <document>, errorsOnly: <boolean>, cursor: { batchSize: <integer> }, writeConcern: <string> } )
在命令语法中,您可以指定多个:
在
ops
大量中以任意顺序执行插入、更新和删除操作。nsInfo
大量中操作的命名空间。 要将操作与命名空间匹配,请使用相同的命名空间ID索引。 索引从0
开始。 您可以使用分片的集合。
命令字段
该命令接受以下字段:
字段 | 类型 | 必要性 | 说明 |
---|---|---|---|
| 整型 | 必需 | 插入操作的命名空间ID索引,必须与 |
| 文档 | 必需 | 要插入到集合中的文档。 |
| 整型 | 必需 | 更新操作的命名空间ID索引,必须与 |
| 文档 | Optional | 查询选择器,用于限制进行更新或删除操作的文档。 |
| 文档 | Optional | |
| 文档数组 | Optional | 过滤文档数组,指定针对大量字段的更新操作要修改的文档。 有关详细信息,请参阅使用 |
| 布尔 | Optional | 如果 默认值为 |
| 文档 | Optional | 用于文档 |
| 文档 | Optional | 用于聚合管道自定义更新的常量。 |
| 文档 | Optional | 更新或删除操作的排序规则。 |
| 整型 | 必需 | 删除操作的命名空间ID索引,必须与 |
| 字符串 | 必需 | 操作的命名空间(数据库和集合)。 将 |
| 字符串 | Optional | 指定操作集合的UUID十六进制值。 |
| 文档 | Optional | 操作的加密信息模式和令牌。 有关详细信息,请参阅加密模式。 |
| 布尔 | Optional | 如果 有序操作会串行运行。 如果发生错误,将取消所有剩余操作。 无序操作并行运行。 如果发生错误,则运行剩余的所有语句。 服务器可以对这些操作重新排序,以提高性能。 因此,您的应用程序不应依赖于操作的执行顺序。 默认值为 |
| 布尔 | Optional | 如果为 默认值为 |
| 字符串 | Optional | 可选。用户提供的待附加到该命令的注释。设置后,该注释将与该命令的记录一起出现在以下位置:
注释可以是任何有效的 BSON 类型(字符串、整型、对象、数组等)。 |
| 文档 | Optional | 包含要在操作中引用的常量列表的文档。 有关 |
| 布尔 | Optional | 如果为 默认值为 |
| 整型 | Optional |
|
| 字符串 | Optional | 写入操作的关注点。 省略使用服务器默认。 |
输出
该命令返回包含以下字段的文档:
字段 | 类型 | 说明 |
---|---|---|
| 文档 | 游标带有命令结果。 |
| 整型 | 游标标识符。 |
| 文档数组 | 操作结果。 |
| 整型 |
|
| 整型 | 操作索引号,对应于 |
| 整型 | 错误的代码号。 |
| 字符串 | 错误描述。 |
| 字符串 | 文档索引键规范是否存在错误。 |
| 字符串 | 发生错误的文档索引键值。 |
| 整型 | 受操作影响的文档总数。 |
| 整型 | 更新操作修改的文档数量。 |
| 整型 |
|
| 整型 | 插入的文档数。 |
| 整型 | 匹配的文档数量。 |
| 整型 | 已修改文档的数量。 |
| 整型 | 已更新或插入的文档数量。 |
| 整型 | 已删除文档的数量。 |
| 整型 |
|
注意
输出字段可能会有所不同,具体取决于您在bulkWrite
命令中运行的操作。
行为
本部分介绍bulkWrite
命令行为。
多文档字段和可重试写入
如果multi
字段为true
,则更新或删除操作将更新或删除与文档filter
匹配的所有文档。 如果为false
,则操作更新或删除与文档filter
匹配的第一个文档。 有关多文档事务的详细信息,请参阅事务。
要启用重试写入,请参阅可重试写入。
您可以使用具有可重试写入功能的bulkWrite
插入操作,并将multi
字段设立为true
。
您可以使用bulkWrite
更新和删除操作,并将multi
字段设立为true
。 但是,在将multi
设立为true
和可重试写入的情况下,您无法使用更新或删除操作。
操作性能
如果将现有的插入、更新和删除命令重写为bulkWrite
命令设立errorsOnly
设置为true
,则bulkWrite
命令具有与现有命令相似的性能。 如果设立errorsOnly
设置为false
,性能会变差。
此外,如果您有如下命令序列:
insert update delete
如果将这些命令替换为以下示例片段,则无论其他选项如何,使用以下片段的命令都会更快:
{ bulkWrite: 1, ops: [ insert, update, delete ] }
大部分性能改进是由于网络延迟造成的,网络延迟因实施而异,但示例总是速度更快。
示例
本部分包含bulkWrite
命令示例。
单个命名空间批量写入示例
以下bulkWrite
示例修改了单个命名空间:
修改披萨示例集合
运行以下bulkWrite
命令以对pizzas
集合执行插入、更新和删除操作:
db.adminCommand( { bulkWrite: 1, // The ops array contains the insert, update, and delete // operations. ops: [ // Specify the namespace ID index immediately after // the insert, update, and delete text. // For example, "insert: 0" specifies the 0 namespace ID index, // which is the "test.pizzas" namespace in nsInfo at the end // of the example. // Insert a pizza. { insert: 0, document: { _id: 4, type: "sausage", size: "small", price: 12 } }, // Update the price for medium pizzas. { update: 0, filter: { size: "medium" }, updateMods: { $set: { price: 15 } } }, // Delete the pizza with an _id of 2. { delete: 0, filter: { _id: 2 } } ], // The nsInfo array contains the namespace to apply the // previous operations to. nsInfo: [ { ns: "test.pizzas" } // Namespace ID index is 0. ] } )
pizzas
集合位于默认的test
数据库中,因此ns
命名空间为"test.pizzas"
。 命名空间ID索引为0
,它在ops
大量中的插入、更新和删除操作的第一个字段中设立。
检查输出
以下bulkWrite
示例输出包含各个ok: 1
字段和nErrors: 0
,表示所有操作均已成功:
{ cursor: { id: Long('0'), firstBatch: [ { ok: 1, idx: 0, n: 1 }, { ok: 1, idx: 1, n: 1, nModified: 1 }, { ok: 1, idx: 2, n: 1 } ], ns: 'admin.$cmd.bulkWrite' }, nErrors: 0, nInserted: 1, nMatched: 1, nModified: 1, nUpserted: 0, nDeleted: 1, ok: 1 }
有关输出字段的详细信息,请参阅前面的输出部分。
多个命名空间批量写入示例
您可以在bulkWrite
命令中指定多个命名空间。
以下bulkWrite
示例包含针对两个命名空间的插入、更新和删除操作:
创建披萨示例集合
如果test
数据库中已有pizzas
集合,请先使用db.collection.drop()
方法将其删除,然后运行:
db.pizzas.insertMany( [ { _id: 0, type: "pepperoni", size: "small", price: 4 }, { _id: 1, type: "cheese", size: "medium", price: 7 }, { _id: 2, type: "vegan", size: "large", price: 8 } ] )
创建披萨订单示示例集合
运行:
db.pizzaOrders.insertMany( [ { _id: 0, type: "pepperoni", number: 5, orderDate: new Date( "2023-01-15T12:00:00Z" ) }, { _id: 1, type: "cheese", number: 15, orderDate: new Date( "2023-01-23T11:12:32Z" ) }, { _id: 2, type: "vegan", number: 20, orderDate: new Date( "2023-03-20T10:01:12Z" ) } ] )
修改示例集合
运行以下bulkWrite
命令,对示例集合执行插入、更新和删除操作:
db.adminCommand( { bulkWrite: 1, // The ops array contains the insert, update, and delete // operations. ops: [ // Specify the namespace ID indexes immediately after // the insert, update, and delete. For example, "insert: 0" // specifies the 0 namespace ID index, which is the "test.pizzas" // namespace. And, "insert: 1" specifies "test.pizzaOrders". // Insert pizzas. // Namespace ID is 0 for "test.pizzas", which // is specified as "insert: 0". { insert: 0, document: { _id: 5, type: "sausage", size: "small", price: 12 } }, { insert: 0, document: { _id: 6, type: "vegan cheese", size: "large", price: 25 } }, // Update the price for cheese pizzas. { update: 0, filter: { type: "cheese" }, updateMods: { $set: { price: 15 } } }, // Delete pizzas with a price less than 7. { delete: 0, filter: { price: { $lt: 7 } } }, // Insert pizza orders. // Namespace ID is 1 for "test.pizzaOrders". { insert: 1, document: { _id: 3, type: "sausage", number: 7, orderDate: new Date( "2023-04-15T12:02:15Z" ) } }, { insert: 1, document: { _id: 4, type: "vegan", number: 16, orderDate: new Date( "2023-05-12T11:03:11Z" ) } }, // Update the number of pizza orders for cheese pizzas. { update: 1, filter: { type: "cheese" }, updateMods: { $set: { number: 50 } } }, // Delete the pizza order with an _id of 2. { delete: 1, filter: { _id: 2 } }, // Delete pizza orders placed before March 15, 2023. { delete: 1, filter: { orderDate: { $lte: ISODate( "2023-03-15T00:00:00Z" ) } } } ], // Namespaces nsInfo: [ { ns: "test.pizzas" }, // Namespace ID index is 0. { ns: "test.pizzaOrders" } // Namespace ID index is 1. ] } )
检查输出
以下bulkWrite
示例输出表示操作成功:
{ cursor: { id: Long('0'), firstBatch: [ { ok: 1, idx: 0, n: 1 }, { ok: 1, idx: 1, n: 1 }, { ok: 1, idx: 2, n: 1, nModified: 1 }, { ok: 1, idx: 3, n: 1 }, { ok: 1, idx: 4, n: 1 }, { ok: 1, idx: 5, n: 1 }, { ok: 1, idx: 6, n: 1, nModified: 1 }, { ok: 1, idx: 7, n: 1 }, { ok: 1, idx: 8, n: 1 } ], ns: 'admin.$cmd.bulkWrite' }, nErrors: 0, nInserted: 4, nMatched: 2, nModified: 2, nUpserted: 0, nDeleted: 3, ok: 1 }
出现错误的操作批量写入示例
以下bulkWrite
示例包含出现错误的操作和不更改任何文档的操作:
创建披萨示例集合
如果test
数据库中已有pizzas
集合,请先使用db.collection.drop()
方法将其删除,然后运行:
db.pizzas.insertMany( [ { _id: 0, type: "pepperoni", size: "small", price: 4 }, { _id: 1, type: "cheese", size: "medium", price: 7 }, { _id: 2, type: "vegan", size: "large", price: 8 } ] )
尝试修改披萨示例集合
运行以下bulkWrite
命令以对pizzas
集合执行插入、更新和删除操作:
db.adminCommand( { bulkWrite: 1, // The ops array contains the insert, update, and delete // operations. ops: [ // The namespace ID indexes are specified immediately after // the insert, update, and delete text. // For example, "insert: 0" specifies the 0 namespace ID index, // which is the "test.pizzas" namespace in nsInfo. // Attempt to add a duplicate document with an // _id of 1, which already exists and causes an error. { insert: 0, document: { _id: 1, type: "tomato", size: "small", price: 12 } }, // Attempt to add another duplicate document. { insert: 0, document: { _id: 2, type: "pepper", size: "small", price: 12 } }, // Attempt to change the price for extra large pizzas, // which don't exist. This doesn't cause an error but // doesn't update any documents. { update: 0, filter: { size: "extra large" }, updateMods: { $set: { price: 15 } } }, // Attempt to remove a document that doesn't exist. // This doesn't cause an error but doesn't delete any documents. { delete: 0, filter: { _id: 8 } } ], // The nsInfo array contains the namespace to apply the // previous operations to. nsInfo: [ { ns: "test.pizzas" } // Namespace ID index is 0. ], // Set the ordered field to false to run the remaining operations // after an operation returns an error. ordered: false } )
检查输出
以下bulkWrite
示例输出显示了这些错误:
{ cursor: { id: Long("0"), firstBatch: [ { ok: 0, idx: 0, code: 11000, errmsg: 'E11000 duplicate key error collection: test.pizzas index: _id_ dup key: { _id: 1 }', keyPattern: { _id: 1 }, keyValue: { _id: 1 }, n: 0 }, { ok: 0, idx: 1, code: 11000, errmsg: 'E11000 duplicate key error collection: test.pizzas index: _id_ dup key: { _id: 2 }', keyPattern: { _id: 1 }, keyValue: { _id: 2 }, n: 0 }, { ok: 1, idx: 2, n: 0, nModified: 0 }, { ok: 1, idx: 3, n: 0 } ], ns: 'admin.$cmd.bulkWrite' }, nErrors: 2, nInserted: 0, nMatched: 0, nModified: 0, nUpserted: 0, nDeleted: 0, ok: 1 }
有关输出字段的详细信息,包括错误代码和消息,请参阅前面的输出部分。
启用errorsOnly 的批量写入示例
以下bulkWrite
示例将errorsOnly
设置为true
以仅显示错误输出:
创建披萨示例集合
如果test
数据库中已有pizzas
集合,请先使用db.collection.drop()
方法将其删除,然后运行:
db.pizzas.insertMany( [ { _id: 0, type: "pepperoni", size: "small", price: 4 }, { _id: 1, type: "cheese", size: "medium", price: 7 }, { _id: 2, type: "vegan", size: "large", price: 8 } ] )
尝试修改披萨示例集合
运行以下bulkWrite
命令,对pizzas
集合执行插入、更新和删除操作,其中errorsOnly
设立为true
:
db.adminCommand( { bulkWrite: 1, // The ops array contains the insert, update, and delete // operations. ops: [ // The namespace ID indexes are specified immediately after // the insert, update, and delete text. // For example, "insert: 0" specifies the 0 namespace ID index, // which is the "test.pizzas" namespace in nsInfo. // Attempt to add a duplicate document with an // _id of 1, which already exists and causes an error. { insert: 0, document: { _id: 1, type: "tomato", size: "small", price: 12 } }, // Attempt to add another duplicate document. { insert: 0, document: { _id: 2, type: "pepper", size: "small", price: 12 } }, // Attempt to change the price for extra large pizzas, // which don't exist. This doesn't cause an error but // doesn't update any documents. { update: 0, filter: { size: "extra large" }, updateMods: { $set: { price: 15 } } }, // Attempt to remove a document that doesn't exist. // This doesn't cause an error but doesn't delete any documents. { delete: 0, filter: { _id: 8 } } ], // The nsInfo array contains the namespace to apply the // previous operations to. nsInfo: [ { ns: "test.pizzas" } // Namespace ID index is 0. ], // Set the ordered field to false to run the remaining operations // after an operation returns an error. ordered: false, // Set the errorsOnly field to true to only output the errors. errorsOnly: true } )
检查输出
以下bulkWrite
示例输出显示了这些错误:
{ cursor: { id: Long("0"), firstBatch: [ { ok: 0, idx: 0, code: 11000, errmsg: 'E11000 duplicate key error collection: test.pizzas index: _id_ dup key: { _id: 1 }', keyPattern: { _id: 1 }, keyValue: { _id: 1 }, n: 0 }, { ok: 0, idx: 1, code: 11000, errmsg: 'E11000 duplicate key error collection: test.pizzas index: _id_ dup key: { _id: 2 }', keyPattern: { _id: 1 }, keyValue: { _id: 2 }, n: 0 }, ], ns: 'admin.$cmd.bulkWrite' }, nErrors: 2, nInserted: 0, nMatched: 0, nModified: 0, nUpserted: 0, nDeleted: 0, ok: 1 }