db.collection.insertMany()
MongoDB与驱动程序一起使用
本页文档了一个mongosh 方法。要查看特定编程语言的等效方法,请参阅相应页面
定义
db.collection.insertMany()将多个文档插入到集合中。
返回: 包含以下内容的文档:
一个
acknowledged布尔值,如果操作在write concern下运行,则设置为true,如果禁用了 write concern,则设置为falsewrite concern:有关详细信息,请参阅 write concern一个
insertedIds数组,包含每个成功插入文档的_id值
兼容性
此方法在以下环境中托管的应用程序中可用:
MongoDB Atlas:MongoDB 集成云部署的完全托管服务
注意
此命令在所有 MongoDB Atlas 集群中都受支持。有关所有命令的 Atlas 支持信息,请参阅 不受支持的命令。
MongoDB Enterprise:MongoDB 的基于订阅的、自我管理的版本
MongoDB Community:MongoDB 的源代码可用、免费使用和自我管理的版本
语法
方法 insertMany() 的语法如下
db.collection.insertMany( [ <document 1> , <document 2>, ... ], { writeConcern: <document>, ordered: <boolean> } )
参数 | 类型 | 描述 |
|---|---|---|
document | document | 要插入集合中的文档数组。 |
writeConcern | document | 可选。一个表示 write concern 的文档。省略则使用默认的write concern。 如果在事务中运行操作,不要显式设置写关注。要使用事务中的写关注,请参阅 事务和写关注。 |
ordered | 布尔值 | 可选。一个布尔值,指定 mongod 实例应该执行有序或无序插入。默认为 true。 |
行为
给定一个文档数组,insertMany() 将数组中的每个文档插入到集合中。
操作执行
默认情况下,文档将按照提供的顺序插入。
如果将ordered设置为true并且插入操作失败,服务器将不会继续插入记录。
如果将ordered设置为false并且插入操作失败,服务器将继续插入记录。文档可能会被mongod重新排序以提高性能。当使用无序的insertMany()时,应用程序不应依赖于插入操作的顺序。
每个组中的操作数不能超过数据库的maxWriteBatchSize值。默认的maxWriteBatchSize值为100,000。此值在hello.maxWriteBatchSize字段中显示。
此限制防止了过大的错误消息问题。如果组超过此限制,客户端驱动程序会将该组划分为更小的组,这些组的计数小于或等于限制值。例如,当maxWriteBatchSize值为100,000时,如果队列包含200,000个操作,驱动程序将创建2个组,每个组有100,000个操作。
注意
驱动程序仅在使用高级API时才会将组划分为更小的组。如果直接使用db.runCommand()(例如,在编写驱动程序时),当尝试执行超过限制的写批处理时,MongoDB会抛出错误。
如果单个批次的错误报告变得过大,MongoDB会将所有剩余的错误消息截断为空字符串。如果有至少两个总大小大于1MB的错误消息,它们将被截断。
大小和分组机制是内部性能细节,未来版本中可能会有所变化。
在分片集合上执行有序操作列表通常比执行无序列表慢,因为在有序列表中,每个操作必须等待前一个操作完成。
集合创建
如果集合不存在,则insertMany()在成功写入时创建集合。
_id 字段
如果文档未指定 _id 字段,则 mongod 会添加 _id 字段并分配一个唯一的 ObjectId() 给文档。大多数驱动程序创建 ObjectId 并插入 _id 字段,但如果驱动程序或应用程序没有做,则 mongod 会创建并填充 _id 字段。
如果文档包含 _id 字段,则 _id 的值必须在集合中是唯一的,以避免重复键错误。
可解释性
错误处理
插入操作会抛出 BulkWriteError 异常。
除了 写关注 错误外,有序操作在出现错误后停止,而无序操作将继续处理队列中的任何剩余写操作。
写入关注错误显示在 writeConcernErrors 字段中,而所有其他错误显示在 writeErrors 字段中。如果遇到错误,将显示成功写入操作的数量而不是插入 _ids 的列表。有序操作显示遇到的单个错误,而无序操作显示数组中的每个错误。
模式验证错误
如果您的集合使用 模式验证 并将 validationAction 设置为 error,则使用 db.collection.insertMany() 插入无效文档将引发 writeError。在 documents 数组中位于无效文档之前的文档将被写入集合。ordered 字段的值确定是否插入剩余的有效文档。
事务
db.collection.insertMany() 可用于 分布式事务 中。
重要
在大多数情况下,分布式事务比单个文档写入产生更大的性能成本,分布式事务的可用性不应替代有效的模式设计。对于许多场景,非规范化数据模型(嵌套文档和数组) 将继续是您数据和用例的最佳选择。也就是说,在许多场景中,适当地建模数据将最大限度地减少分布式事务的需求。
有关事务使用的其他考虑事项(例如运行时限制和 oplog 大小限制),请参阅生产注意事项。
事务中创建集合
如果事务不是跨分片写事务,您可以在 分布式事务 中创建集合和索引。不 是跨分片写事务。
如果在事务中指定对不存在集合的插入操作,MongoDB 会隐式创建该集合。
写入关注点和事务
如果在事务中运行操作,不要显式设置写关注。要使用事务中的写关注,请参阅 事务和写关注。
随机数据性能考虑
如果在索引字段上执行的操作插入大量随机数据(例如,散列索引),则插入性能可能会下降。随机数据的批量插入会创建随机的索引条目,这会增加索引的大小。如果索引达到需要每个随机插入都访问不同索引条目的大小,则插入会导致 WiredTiger 缓存淘汰和替换的比率很高。当发生这种情况时,索引不再完全在缓存中,而是在磁盘上更新,这会降低性能。
为了提高索引字段上批量插入随机数据的性能,您可以
先删除索引,然后插入随机数据后再重新创建它。
将数据插入到一个空的非索引集合中。
在批量插入后创建索引,这将在内存中对数据进行排序,并对所有索引执行有序插入。
Oplog条目
如果db.collection.insertMany()操作成功插入一个或多个文档,则该操作会在每个插入的文档的操作日志(oplog)上添加一个条目。如果操作失败,则不会在oplog上添加条目。
示例
以下示例将文档插入到products集合中。
不指定_id字段插入多个文档
以下示例使用db.collection.insertMany()插入不包含_id字段的文档
try { db.products.insertMany( [ { item: "card", qty: 15 }, { item: "envelope", qty: 20 }, { item: "stamps" , qty: 30 } ] ); } catch (e) { print (e); }
操作返回以下文档
{ "acknowledged" : true, "insertedIds" : [ ObjectId("562a94d381cb9f1cd6eb0e1a"), ObjectId("562a94d381cb9f1cd6eb0e1b"), ObjectId("562a94d381cb9f1cd6eb0e1c") ] }
由于文档没有包含_id,mongod为每个文档创建并添加了_id字段,并为其分配了唯一的ObjectId()值。
ObjectId值与操作运行时的机器和时间有关。因此,您的值可能与示例中的值不同。
插入多个指定 _id 字段的文档
以下示例/操作使用 insertMany() 插入包含 _id 字段的文档。为了防止重复键错误,_id 的值必须在集合中是唯一的。
try { db.products.insertMany( [ { _id: 10, item: "large box", qty: 20 }, { _id: 11, item: "small box", qty: 55 }, { _id: 12, item: "medium box", qty: 30 } ] ); } catch (e) { print (e); }
操作返回以下文档
{ "acknowledged" : true, "insertedIds" : [ 10, 11, 12 ] }
在 唯一索引 中插入任何键的重复值,如 _id,将抛出异常。以下尝试插入具有已存在 _id 值的文档
try { db.products.insertMany( [ { _id: 13, item: "envelopes", qty: 60 }, { _id: 13, item: "stamps", qty: 110 }, { _id: 14, item: "packing tape", qty: 38 } ] ); } catch (e) { print (e); }
由于 _id: 13 已经存在,以下异常被抛出
BulkWriteError({ "writeErrors" : [ { "index" : 0, "code" : 11000, "errmsg" : "E11000 duplicate key error collection: inventory.products index: _id_ dup key: { : 13.0 }", "op" : { "_id" : 13, "item" : "stamps", "qty" : 110 } } ], "writeConcernErrors" : [ ], "nInserted" : 1, "nUpserted" : 0, "nMatched" : 0, "nModified" : 0, "nRemoved" : 0, "upserted" : [ ] })
请注意,已插入一个文档:第一个 _id: 13 的文档将成功插入,但第二次插入将失败。这还将停止队列中剩余的文档插入。
将 ordered 设置为 false,则插入操作将继续进行任何剩余的文档。
无序插入
以下尝试使用 _id 字段和 ordered: false 插入多个文档。文档数组包含两个具有重复 _id 字段的文档。
try { db.products.insertMany( [ { _id: 10, item: "large box", qty: 20 }, { _id: 11, item: "small box", qty: 55 }, { _id: 11, item: "medium box", qty: 30 }, { _id: 12, item: "envelope", qty: 100}, { _id: 13, item: "stamps", qty: 125 }, { _id: 13, item: "tape", qty: 20}, { _id: 14, item: "bubble wrap", qty: 30} ], { ordered: false } ); } catch (e) { print (e); }
操作抛出以下异常
BulkWriteError({ "writeErrors" : [ { "index" : 2, "code" : 11000, "errmsg" : "E11000 duplicate key error collection: inventory.products index: _id_ dup key: { : 11.0 }", "op" : { "_id" : 11, "item" : "medium box", "qty" : 30 } }, { "index" : 5, "code" : 11000, "errmsg" : "E11000 duplicate key error collection: inventory.products index: _id_ dup key: { : 13.0 }", "op" : { "_id" : 13, "item" : "tape", "qty" : 20 } } ], "writeConcernErrors" : [ ], "nInserted" : 5, "nUpserted" : 0, "nMatched" : 0, "nModified" : 0, "nRemoved" : 0, "upserted" : [ ] })
尽管具有 item: "medium box" 和 item: "tape" 的文档由于重复 _id 值而插入失败,但 nInserted 显示剩余 5 个文档已插入。
使用写入关注度
对于一个由三个成员组成的副本集,以下操作指定了大多数写入关注度(w)和超时时间(wtimeout)为100。
try { db.products.insertMany( [ { _id: 10, item: "large box", qty: 20 }, { _id: 11, item: "small box", qty: 55 }, { _id: 12, item: "medium box", qty: 30 } ], { w: "majority", wtimeout: 100 } ); } catch (e) { print (e); }
如果主节点和至少一个副节点在100毫秒内确认每个写入操作,则返回
{ "acknowledged" : true, "insertedIds" : [ ObjectId("562a94d381cb9f1cd6eb0e1a"), ObjectId("562a94d381cb9f1cd6eb0e1b"), ObjectId("562a94d381cb9f1cd6eb0e1c") ] }
如果副本集中所有所需节点确认写入操作所需的总时间大于wtimeout,则在wtimeout周期过后,将显示以下writeConcernError错误。
此操作返回
WriteConcernError({ "code" : 64, "errmsg" : "waiting for replication timed out", "errInfo" : { "wtimeout" : true, "writeConcern" : { "w" : "majority", "wtimeout" : 100, "provenance" : "getLastErrorDefaults" } } })