带驱动程序的 MongoDB
本页面提供 mongosh 方法的相关信息。要查看 MongoDB 驱动程序中的等效方法,请参阅编程语言的相应页面:
注意
MongoDB 8.0 中的新批量写入命令
从 MongoDB 8.0 开始,您可以使用 Mongo.bulkWrite() mongosh 方法在多个数据库和集合中执行批量写入。要了解更多关于不同批量写入方法和命令的信息,请参阅批量写入操作。
定义
db.collection.bulkWrite()在一个集合上执行多个写入操作,并控制执行顺序。
返回: - 如果操作使用写关注来运行,则
acknowledged布尔值为true;如果已禁用写关注,则为false。 - 每个写入操作的计数。
- 一个数组:为每份成功插入或更新的文档一个
_id。
- 如果操作使用写关注来运行,则
兼容性
db.collection.bulkWrite() 在以下环境中托管的部署中可用:
MongoDB Atlas:用于云中 MongoDB 部署的完全托管服务
注意
所有 MongoDB Atlas 集群都支持此命令。有关 Atlas 对所有命令的支持的信息,请参阅不支持的命令。
MongoDB Enterprise:基于订阅、自我管理的 MongoDB 版本
MongoDB Community:源代码可用、免费使用且可自行管理的 MongoDB 版本
注意
您无法在 Atlas UI 中执行批量写入操作。要插入多个文档,必须插入一组文档。要了解更多信息,请参阅 Atlas 文档中的创建、查看、更新和删除文档。
语法
bulkWrite() 方法采用以下形式:
db.collection.bulkWrite( [ <operation 1>, <operation 2>, ... ], { writeConcern : <document>, ordered : <boolean> } )
参数
bulkWrite() 方法采用以下参数:
Parameter | 类型 | 说明 | ||
|---|---|---|---|---|
| 阵列 | 一个包含 有效操作包括: | ||
| 文档 | |||
| 布尔 | 可选。布尔值,指定操作是串行执行( |
行为
bulkWrite() 获取一系列写入操作并执行每个写入操作。默认情况下,操作按顺序执行。有关控制写入操作执行顺序的信息,请参见执行操作。
写入操作
insertOne
将单个文档插入集合中。
db.collection.bulkWrite( [ { insertOne : { "document" : <document> } } ] )
updateOne 和 updateMany
updateOne 更新集合中与过滤器匹配的单个文档。如果存在多个匹配的文档,updateOne 将只更新第一个匹配的文档。
db.collection.bulkWrite( [ { updateOne : { "filter": <document>, "update": <document or pipeline>, "upsert": <boolean>, "collation": <document>, "arrayFilters": [ <filterdocument1>, ... ], "hint": <document|string> } } ] )
updateMany 更新集合中与过滤器匹配的所有文档。
db.collection.bulkWrite( [ { updateMany : { "filter" : <document>, "update" : <document or pipeline>, "upsert" : <boolean>, "collation": <document>, "arrayFilters": [ <filterdocument1>, ... ], "hint": <document|string> } } ] )
字段 | 注意 |
|---|---|
| 更新的选择条件。可以使用与 |
| |
| 可选。一个布尔值,表明是否执行更新插入操作。 默认情况下, |
| 选修的。大量过滤器文档,用于确定针对大量字段的更新操作要修改哪些大量元素。 |
| 可选。指定用于操作的排序规则。 |
| 可选。用于支持更新 |
replaceOne
replaceOne 将替换集合中与筛选器匹配的单个文档。如果存在多个匹配的文档,replaceOne 将只替换第一个匹配的文档。
db.collection.bulkWrite([ { replaceOne : { "filter" : <document>, "replacement" : <document>, "upsert" : <boolean>, "collation": <document>, "hint": <document|string> } } ] )
字段 | 注意 |
|---|---|
| 替换操作的选择条件。可以使用与 |
| 替换文档。文档不能包含更新操作符。 |
| 可选。一个布尔值,表明是否执行更新插入操作。默认情况下, |
| 可选。指定用于操作的排序规则。 |
| 可选。用于支持更新 |
deleteOne 和 deleteMany
deleteOne 删除集合中与过滤器匹配的单个文档。如果存在多个匹配的文档,deleteOne 将只删除第一个匹配的文档。
db.collection.bulkWrite([ { deleteOne : { "filter" : <document>, "collation" : <document> // Available starting in 3.4 } } ] )
deleteMany 删除集合中与过滤器匹配的所有文档。
db.collection.bulkWrite([ { deleteMany: { "filter" : <document>, "collation" : <document> // Available starting in 3.4 } } ] )
字段 | 注意 |
|---|---|
| 删除操作的选择条件。可以使用与 |
| 可选。指定用于操作的排序规则。 |
_id 字段
如果文档未指定 _id 字段,则 mongod 会添加 _id 字段,并在插入或更新该文档之前为其分配唯一的 ObjectId() 字段。多数驱动程序都会创建一个 ObjectId 并插入 _id 字段,但如果驱动程序或应用程序不这样做,则 mongod 将创建并填充 _id。
如果文档包含 _id 字段,则 _id 值在集合中必须是唯一的,以避免重复键错误。
更新或替换操作不能指定与原始文档不同的 _id 值。
执行操作
ordered 参数控制操作是串行执行还是以任意顺序执行。
使用 ordered : true(默认)时,操作会串行执行。如果发生错误,则不会执行后续操作。
使用 ordered : false,操作可以并行执行。即使某些操作失败,所有没有错误的操作也会完成。
每组中的操作次数不得超过数据库的 maxWriteBatchSize 值。maxWriteBatchSize 的默认值为 100,000。该值会显示在 hello.maxWriteBatchSize 字段中。
此限制可防止错误消息过大的问题。如果一个群组超过此限制,则客户端驱动程序会将该群组分成计数小于或等于限制值的更小群组。例如,对于 maxWriteBatchSize 值为 100,000 的情况,如果队列由 200,000 个操作组成,则驱动程序将创建 2 个群组,每个群组包含 100,000 个操作。
注意
该驱动程序仅在使用高级 API 时会将上述群组划分为多个更小的群组。如果直接使用 db.runCommand()(例如,在编写驱动程序时),MongoDB 在尝试执行超过限制的写入批处理时会引发错误。
如果单个批处理的错误报告变得过大,MongoDB 会将所有剩余的错误消息截断为空字符串。如果至少存在两条总大小大于 1MB 的错误消息,则会将其截断。
大小和分组机制是内部性能细节,在未来版本中可能会有变化。
在分片集合上执行操作的 ordered 列表通常比执行 unordered 列表慢,因为对于有序列表,每个操作都必须等待前一个操作完成。
固定大小集合
bulkWrite() 对固定大小集合有限制:
updateOne和updateMany会在更新增加文档大小时抛出WriteError。replaceOne如果替换文档大于原始文档,则会抛出WriteError。deleteOne和deleteMany对固定大小集合抛出WriteError。
Error Handling
bulkWrite() BulkWriteError会在出现错误时引发 异常。请参阅事务中的错误处理。
当排除了写关注错误时,有序操作将在发生错误之后停止,而无序操作会继续处理队列中的任何剩余写操作(除非在事务内运行)。请参阅事务中的错误处理。
写关注错误显示在 writeConcernErrors 字段中,所有其他错误显示在 writeErrors 字段中。如果遇到错误,将显示成功的写入操作的数量,而不是插入的 _id 值。有序操作会显示遇到的单个错误,而无序操作会显示数组中的每个错误。
模式验证错误
如果您的集合使用模式验证并将validationAction设立为error ,则插入无效文档或使用无效值更新文档会引发错误。 执行operations大量中无效操作之前的操作并将其写入集合。 ordered字段决定是否执行剩余操作。
事务
bulkWrite() 可用于分布式事务。
重要
在大多数情况下,与单文档写入操作相比,分布式事务会产生更高的性能成本,并且分布式事务的可用性不应取代有效的模式设计。在许多情况下,非规范化数据模型(嵌入式文档和数组)仍然是数据和使用案例的最佳选择。换言之,对于许多场景,适当的数据建模将最大限度地减少对分布式事务的需求。
有关其他事务使用注意事项(如运行时间限制和 oplog 大小限制),另请参阅生产注意事项。
在事务中插入和更新插入
对于特征兼容性版本 (fcv) "4.4" 及更高版本,如果在事务中对不存在的集合执行了插入操作或更新操作 (upsert: true),则会隐式创建该集合。
注意
您无法在跨分片写事务中创建新集合。例如,如果您在一个分片中写入一个现有集合,并在另一个分片中隐式创建一个集合,MongoDB 将无法在同一事务中执行这两个操作。
写关注和事务
如果是在事务中运行,则请勿显式设置此操作的写关注。要将写关注与事务一起使用,请参阅事务和写关注。
事务内部的错误处理
从 MongoDB 4.2 开始,如果 db.collection.bulkWrite() 操作在事务内部遇到错误,则该方法会抛出 BulkWriteException(与在事务外部相同)。
在 4.0 中,如果 bulkWrite 操作在事务内遇到错误,则引发的错误不会包装为 BulkWriteException。
在事务内部,批量写入中的第一个错误会导致整个批量写入失败并中止事务,即使批量写入是无序的也是如此。
示例
本页上的示例使用 sample_mflix示例数据集中的数据。有关如何将此数据集加载到自管理MongoDB 部署中的详细信息,请参阅加载示例数据集。如果对示例数据库进行了任何修改,则可能需要删除并重新创建数据库才能运行本页上的示例。
无序批量写入示例
要指定无序 bulkWrite(),请将 ordered设立为 false。
在无序列表的 bulkWrite() 操作列表中:
操作可以并行运行(不保证)。有关详细信息,请参阅有序操作和无序操作。
出现错误的操作未完成。
所有无错误的操作都已完成。
在以下示例中:
bulkWrite()对users集合运行无序操作。已注释掉的第二个
insertOne操作具有与第一个insertOne相同的_id,这会导致重复键错误。
db.users.bulkWrite( [ { insertOne: { document: { _id: ObjectId("67a1b2c3d4e5f6a7b8c9d0e9"), name: "Sansa Stark", email: "sansa.stark@example.com", password: "$2b$12$UREFwsRUoyF0CRqGNK0LzO0HM/jLhgUCNNIJ9RJAqMUQ74crlJ1Vu" } } }, // This insert operation with the same _id value as the one above will fail // { insertOne: { // document: { // _id: ObjectId("67a1b2c3d4e5f6a7b8c9d0e9"), // Duplicate _id value // name: "Bran Stark", // email: "bran.stark@example.com", // password: "$2b$12$UREFwsRUoyF0CRqGNK0LzO0HM/jLhgUCNNIJ9RJAqMUQ74crlJ1Vu" // } // } }, { updateOne: { filter: { name: "Catelyn Stark" }, update: { $set: { email: "cat.stark@example.com" } } } }, { deleteOne: { filter: { name: "Ned Stark" } } }, { replaceOne: { filter: { name: "Robb Stark" }, replacement: { name: "Robb Stark", email: "robb.stark@example.com", password: "$2b$12$NewPasswordHashHere123456789012345678901234567890" } } } ], { ordered: false } )
由于重复键错误,第二个 insertOne 操作失败。在无序 bulkWrite() 中, MongoDB完成任何操作都不会出现错误。
分片集群中的写关注错误
在版本8.1.2中进行了更改。
当bulkWrite() mongos在分片集群中的writeConcernError 上执行时,即使出现一个或多个其他错误,响应中也始终会报告 。在以前的版本中,其他错误有时会导致bulkWrite() 不报告写关注(write concern)错误。
示例,如果文档验证失败,触发 DocumentValidationFailed 错误,并且还发生写关注(write concern)错误,则 DocumentValidationFailed 错误和 writeConcernError 都会在响应的顶级字段中返回。
带有写关注的批量写入示例
以下 bulkWrite() 示例对 users 集合运行操作,并设置 "majority" 写关注和 100 毫秒超时:
db.users.bulkWrite( [ { updateMany: { filter: { name: { $regex: /Stark$/ } }, update: { $set: { house: "Stark", verified: false } } } }, { updateOne: { filter: { name: "Ned Stark" }, update: { $set: { title: "Lord of Winterfell" } } } }, { updateOne: { filter: { name: "Catelyn Stark" }, update: { $set: { title: "Lady of Winterfell" } } } } ], { writeConcern: { w: "majority", wtimeout: 100 } } )
如果大多数副本集成员确认操作的时间超过 wtimeout,则该示例将返回写关注(write concern)错误和已完成操作的摘要。