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开始。您可以使用 分片 集合。
命令字段
该命令包含以下字段
字段 | 类型 | 必要性 | 描述 |
|---|---|---|---|
insert | 整数 | 必需 | 插入操作的命名空间ID索引,必须与 ns字段中的命名空间ID索引匹配,该索引位于nsInfo数组中。索引从0开始。 |
document | document | 必需 | 要插入到集合中的文档。 |
update | 整数 | 必需 | 更新操作的命名空间ID索引,必须与 ns字段中的命名空间ID索引匹配,该索引位于nsInfo数组中。索引从0开始。 |
filter | document | 可选 | 查询选择器,用于限制更新或删除操作的文档。 |
updateMods | document | 可选 | |
arrayFilters | 文档数组 | 可选 | 用于指定要修改的文档的过滤文档数组,该文档位于数组字段的更新操作中。 有关详细信息,请参阅使用 |
multi | 布尔值 | 可选 | 如果 默认为 |
hint | document | 可选 | 用于文档 filter的索引。如果索引不存在,则更新操作返回错误。 |
constants | document | 可选 | 用于聚合管道自定义更新的常量。 |
collation | document | 可选 | 更新或删除操作的排序规则。 |
delete | 整数 | 必需 | 删除操作的命名空间ID索引,必须与 ns字段中的命名空间ID索引匹配,该索引位于nsInfo数组中。索引从0开始。 |
ns | 字符串 | 必需 | 操作所在的命名空间(数据库和集合)。在 ops中将每个操作的命名空间ID索引设置为与ns中匹配的命名空间数组索引。索引从0开始。 |
collectionUUID | 字符串 | 可选 | UUID十六进制值,指定操作的集合。 |
encryptionInformation | document | 可选 | 操作的信息架构和令牌。有关详细信息,请参阅加密架构。 |
有序 | 布尔值 | 可选 | 如果 有序操作按顺序运行。如果发生错误,则取消剩余操作。 无序操作并行运行。如果发生错误,则继续运行剩余语句。服务器可能会重新排序操作以提高性能。因此,您的应用程序不应依赖于操作执行的顺序。 默认值为 |
bypassDocumentValidation | 布尔值 | 可选 | 如果 默认为 |
comment | 字符串 | 可选 | 可选。用户提供的注释,用于附加到此命令。一旦设置,此注释将出现在以下位置的此命令记录旁边
注释可以是任何有效的BSON类型(字符串、整数、对象、数组等)。 |
let | document | 可选 | |
errorsOnly | 布尔值 | 可选 | 如果 默认为 |
cursor batchSize | 整数 | 可选 | |
writeConcern | 字符串 | 可选 | 写入关注点。省略以使用服务器默认值。 |
输出
命令返回包含这些字段的文档
字段 | 类型 | 描述 |
|---|---|---|
光标 | document | 带有命令结果的光标。 |
cursor.id | 整数 | 光标标识符。 |
cursor.firstBatch | 文档数组 | 操作结果。 |
cursor.firstBatch.ok | 整数 | 1 表示操作成功。否则,0。 |
cursor.firstBatch.idx | 整数 | 操作索引号,对应于 ops 数组中的操作。第一个操作的 idx 值为 0。 |
cursor.firstBatch.code | 整数 | 错误代码。 |
cursor.firstBatch.errmsg | 字符串 | 错误描述。 |
cursor.firstBatch.keyPattern | 字符串 | 错误文档索引键规范。 |
cursor.firstBatch.keyValue | 字符串 | 错误文档索引键值。 |
cursor.firstBatch.n | 整数 | 受操作影响的文档总数。 |
cursor.firstBatch.nModified | 整数 | 由更新操作修改的文档数。 |
nErrors | 整数 | bulkWrite 命令的错误数。 |
nInserted | 整数 | 插入的文档数。 |
nMatched | 整数 | 匹配的文档数。 |
nModified | 整数 | 修改的文档数。 |
nUpserted | 整数 | 更新的文档数。 |
nDeleted | 整数 | 删除的文档数。 |
ok | 整数 | 1 表示 bulkWrite 命令成功。否则,0。 |
注意
输出字段可能因在 bulkWrite 命令中运行的操作而异。
行为
本节描述了 bulkWrite 命令的行为。
多文档字段和可重试写入
如果multi字段为true,则更新或删除操作更新或删除所有匹配的文档。如果为false,则操作更新或删除第一个匹配的文档。有关多文档事务的详细信息,请参阅事务。
要启用可重试写入,请参阅 可重试写入。
您可以使用带有可重试写入和将multi字段设置为true的bulkWrite插入操作。
您可以使用将multi字段设置为true的bulkWrite更新和删除操作。但是,您不能同时使用将multi设置为true和可重试写入的更新或删除操作。
操作性能
如果您将现有的插入、更新和删除命令重写为bulkWrite命令,并将errorsOnly设置为true,则bulkWrite命令的性能与现有命令相似。如果您将errorsOnly设置为false,性能会变差。
此外,如果您有一系列如下命令
insert update delete
如果您用以下示例片段替换这些命令,则无论其他选项如何,具有以下片段的命令都会更快。
{ bulkWrite: 0, 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 }
有关输出字段的详细信息,包括错误代码和消息,请参阅前面的输出部分。
带有错误 Only 启用的批量写入示例
以下 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 }