创建collection

如果该集合当前不存在,则插入操作将创建该集合。

插入一个文档

Collection.InsertOne 将单个文档插入到集合中。

以下示例将一个新文档插入到inventory集合中。如果文档未指定_id字段,则驱动程序会将_id具有ObjectId值的字段添加到新文档中。请参阅插入特性。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
result, err := coll.InsertOne(
	context.Background(),
	bson.D{
		{"item", "canvas"},
		{"qty", 100},
		{"tags", bson.A{"cotton"}},
		{"size", bson.D{
			{"h", 28},
			{"w", 35.5},
			{"uom", "cm"},
		}},
	})

insertOne()返回包含新插入的文档的_id字段值的文档。有关返回文档的示例,请参见 db.collection.insertOne()参考。

要检索刚刚插入的文档,请查询集合:

1
2
3
4
cursor, err := coll.Find(
	context.Background(),
	bson.D{{"item", "canvas"}},
)

插入多个文档

Collection.InsertMany 可以将多个文档插入一个集合中。

下面的示例将三个新文档插入到 inventory集合中。如果文档未指定_id字段,则驱动程序会将_id具有ObjectId值的字段添加到每个文档中。请参阅插入特性。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
result, err := coll.InsertMany(
	context.Background(),
	[]interface{}{
		bson.D{
			{"item", "journal"},
			{"qty", int32(25)},
			{"tags", bson.A{"blank", "red"}},
			{"size", bson.D{
				{"h", 14},
				{"w", 21},
				{"uom", "cm"},
			}},
		},
		bson.D{
			{"item", "mat"},
			{"qty", int32(25)},
			{"tags", bson.A{"gray"}},
			{"size", bson.D{
				{"h", 27.9},
				{"w", 35.5},
				{"uom", "cm"},
			}},
		},
		bson.D{
			{"item", "mousepad"},
			{"qty", 25},
			{"tags", bson.A{"gel", "blue"}},
			{"size", bson.D{
				{"h", 19},
				{"w", 22.85},
				{"uom", "cm"},
			}},
		},
	})

要检索插入的文档,请查询集合:

1
2
3
4
cursor, err := coll.Find(
	context.Background(),
	bson.D{},
)

特性

集合创建

如果该集合当前不存在,则插入操作将创建该集合。

_id字段

在MongoDB中,存储在集合中的每个文档都需要一个唯一的 _id字段作为主键。如果插入的文档省略了该_id字段,则MongoDB驱动程序会自动为该字段生成一个ObjectId_id。

这也适用于通过upsert:true通过更新操作插入的文档。

原子性

MongoDB中的所有写操作都是单个文档级别的原子操作。

写确认

对于写入问题,您可以指定从MongoDB请求的写入操作的确认级别。

MongoShell方法

MongoDB提供了以下将文档插入到集合中的方法:

db.collection.insertOne()

定义

此小节记录了mongoshell方法,对于相应的MongoDB驱动程序API,请改为参考您特定的MongoDB驱动程序文档。

3.2版中的新功能。

将文档插入集合中。

该insertOne()方法具有以下语法:

1
2
3
4
5
6
db.collection.insertOne(
   <document>,
   {
      writeConcern: <document>
   }
)
参数 类型 描述
document document 要插入集合中的文档。
writeConcern document 可选的。表达文档的写关注。忽略使用默认的写关注。如果在事务中运行,则不要为操作明确设置写关注。要对事务使用写关注,请参见事务和写关注。

返回值:包含以下内容的文档:

  • 一个布尔值acknowledged,true为该操作在运行时带有写关注,false为禁用了写关注点。
  • insertedId为插入文档的_id字段。

特性

集合创建

如果该集合不存在,则该 insertOne()方法将创建该集合。

_id字段

如果文档未指定_id字段,则将在插入之前mongod 添加该_id字段并ObjectId为文档分配唯一性 。大多数驱动程序会创建一个ObjectId并插入该_id字段,但是 如果驱动程序或应用程序未mongod创建,则会创建并填充_id。

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

可解释性

insertOne()不兼容 db.collection.explain()。

使用insert()代替。

错误处理

错误时,db.collection.insertOne()引发writeError 或writeConcernError异常。

事务

db.collection.insertOne()可以在多文档事务中使用。

集合必须已经存在。事务中不允许执行会导致创建新集合的插入操作。

如果在事务中运行,则不要为操作明确设置写关注点。要对事务使用写关注,请参见 事务和写关注

重要 在大多数情况下,与单文档写入相比,多文档事务会产生更高的性能成本,并且多文档事务的可用性不应替代有效的架构设计。在许多情况下, 非规范化数据模型(嵌入式文档和数组)将继续是您的数据和用例的最佳选择。也就是说,在许多情况下,对数据进行适当的建模将最大程度地减少对多文档交易的需求。

有关其他事务使用方面的注意事项(例如运行时限制和oplog大小限制),另请参见生产注意事项

例子

插入文档而不指定_id字段

在以下示例中,传递给该insertOne()方法的文档 不包含该_id 字段:

1
2
3
4
5
try {
   db.products.insertOne( { item: "card", qty: 15 } );
} catch (e) {
   print (e);
};

该操作返回以下文档:

1
2
3
4
{
   "acknowledged" : true,
   "insertedId" : ObjectId("56fc40f9d735c28df206d078")
}

由于文档不包含_id,因此 mongod创建并添加了该_id字段并为其分配了唯一ObjectId值。

这些ObjectId值特定于机器和运行该操作的时间。因此,您的值可能与示例中的值不同。

插入指定_id字段的文档

在以下示例中,传递给该insertOne()方法的文档 包括该_id字段。值_id在集合中必须唯一,以避免重复的键错误。

1
2
3
4
5
try {
   db.products.insertOne( { _id: 10, item: "box", qty: 20 } );
} catch (e) {
   print (e);
}

该操作返回以下内容:

1
{ "acknowledged" : true, "insertedId" : 10 }

为唯一索引(例如)的一部分的任何键插入重复值_id会引发异常。以下尝试插入具有_id已经存在的值的文档:

1
2
3
4
5
try {
   db.products.insertOne( { _id: 10, "item" : "packing peanuts", "qty" : 200 } );
} catch (e) {
   print (e);
}

由于已经存在,因此将引发以下异常:_id: 10

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
WriteError({
   "index" : 0,
   "code" : 11000,
   "errmsg" : "E11000 duplicate key error collection: inventory.products index: _id_ dup key: { : 10.0 }",
   "op" : {
      "_id" : 10,
      "item" : "packing peanuts",
      "qty" : 200
   }
})

提高写入关注

给定一个三成员副本集,以下操作指定w:majority,wtimeoutw:100:

1
2
3
4
5
6
7
8
try {
   db.products.insertOne(
       { "item": "envelopes", "qty": 100, type: "Self-Sealing" },
       { writeConcern: { w : "majority", wtimeout : 100 } }
   );
} catch (e) {
   print (e);
}

如果确认花费的时间超过wtimeout限制,则会引发以下异常:

1
2
3
4
5
6
7
WriteConcernError({
   "code" : 64,
   "errInfo" : {
      "wtimeout" : true
   },
   "errmsg" : "waiting for replication timed out"
})

db.collection.insertMany()

db.collection.insertMany()将多个文档插入集合中。

定义

db.collection.insertMany()

此小节记录了mongoshell方法,对于相应的MongoDB驱动程序API,请改为参考您特定的MongoDB驱动程序文档。

3.2版中的新功能。

将多个文档插入集合中。

该insertMany()方法具有以下语法:

1
2
3
4
5
6
7
db.collection.insertMany(
   [ <document 1> , <document 2>, ... ],
   {
      writeConcern: <document>,
      ordered: <boolean>
   }
)
参数 类型 描述
document document 要插入集合中的一组文档。
writeConcern document 可选的。表达文档的写关注。忽略使用默认的写关注。如果在事务中运行,则不要为操作明确设置写关注。要对事务使用写关注,请参见事务和写关注。
ordered 布尔值 可选的。一个布尔值,指定mongod实例应执行有序插入还是无序插入。默认为true。

返回值:包含以下内容的文档:

  • 一个布尔值acknowledged,就true好像该操作运行时具有写关注或false禁用了写关注
  • 成功插入的文档的数组的每个_id

特性

给定一个文档数组,insertMany() 将数组中的每个文档插入集合中。

操作的执行

默认情况下,按顺序插入文档。

如果ordered设置为false,则文档将以无序格式插入,并且可以通过重新排序mongod来提高性能。如果使用无序,则应用程序不应依赖于insertMany()插入的顺序。

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

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

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

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

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

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

集合创建

如果该集合不存在,则insertMany() 在成功写入时创建该集合。

_id字段

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

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

可解释性

insertMany()与不兼容 db.collection.explain()。

使用insert()代替。

错误处理

插入引发BulkWriteError异常。

排除“写关注”错误后,有序操作将在发生错误后停止,而无序操作将继续处理队列中所有剩余的写操作。

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

事务

db.collection.insertMany()可以在多文档事务中使用。

集合必须已经存在。事务中不允许执行会导致创建新集合的插入操作。

如果在事务中运行,则不要为操作明确设置写关注点。要对事务使用写关注,请参见 事务和写关注。

重要 在大多数情况下,与单文档写入相比,多文档事务会产生更高的性能成本,并且多文档事务的可用性不应替代有效的架构设计。在许多情况下, 非规范化数据模型(嵌入式文档和数组)将继续是您的数据和用例的最佳选择。也就是说,在许多情况下,对数据进行适当的建模将最大程度地减少对多文档交易的需求。

有关其他事务使用方面的注意事项(例如运行时限制和oplog大小限制),另请参见生产注意事项

例子

以下示例将文档插入products 集合中。

插入多个文档而不指定_id字段

以下示例用于db.collection.insertMany()插入不包含该_id字段的文档:

1
2
3
4
5
6
7
8
9
try {
   db.products.insertMany( [
      { item: "card", qty: 15 },
      { item: "envelope", qty: 20 },
      { item: "stamps" , qty: 30 }
   ] );
} catch (e) {
   print (e);
}

该操作返回以下文档:

1
2
3
4
5
6
7
8
{
   "acknowledged" : true,
   "insertedIds" : [
      ObjectId("562a94d381cb9f1cd6eb0e1a"),
      ObjectId("562a94d381cb9f1cd6eb0e1b"),
      ObjectId("562a94d381cb9f1cd6eb0e1c")
   ]
}

由于文档不包含_id, mongod因此_id为每个文档创建并添加字段,并为其分配唯一ObjectId值。

这些ObjectId值特定于机器和运行该操作的时间。因此,您的值可能与示例中的值不同。

插入多个指定_id字段的文档

以下示例/操作用于insertMany()插入包含该_id字段的文档。值_id在集合中必须唯一,以避免重复的键错误。

1
2
3
4
5
6
7
8
9
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);
}

该操作返回以下文档:

1
{ "acknowledged" : true, "insertedIds" : [ 10, 11, 12 ] }

为唯一索引(例如)的一部分的任何键插入重复值都会_id引发异常。以下尝试插入具有_id已经存在的值的文档:

1
2
3
4
5
6
7
8
9
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

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
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

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
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);
}

该操作引发以下异常:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
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" : [ ]
})

尽管由于重复值而有且文档插入失败,但表明剩余的5个文档已插入。

使用写关注

给定一个三成员副本集,以下操作指定 wof majority和wtimeoutof 100:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
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毫秒内确认每个写操作,则返回:

1
2
3
4
5
6
7
8
{
  "acknowledged" : true,
  "insertedIds" : [
     ObjectId("562a94d381cb9f1cd6eb0e1a"),
     ObjectId("562a94d381cb9f1cd6eb0e1b"),
     ObjectId("562a94d381cb9f1cd6eb0e1c")
  ]
}

如果副本集中所有必需节点确认写操作所需的总时间大于wtimeout,则在wtimeout时间段后将显示以下writeConcernError内容。

该操作返回:

1
2
3
4
5
6
7
WriteConcernError({
   "code" : 64,
   "errInfo" : {
      "wtimeout" : true
   },
   "errmsg" : "waiting for replication timed out"
})

其他插入方法

以下方法还可以将新文档添加到集合中:

db.collection.update()与该选项一起使用时:upsert: true db.collection.updateOne()与该选项一起使用时:upsert: true db.collection.updateMany()与该选项一起使用时:upsert: true db.collection.findAndModify()与该选项一起使用时:upsert: true db.collection.findOneAndUpdate()与该选项一起使用时 :upsert: true db.collection.findOneAndReplace()与该选项一起使用时 :upsert: true db.collection.save()。 db.collection.bulkWrite()。

有关更多方法和示例,请参见各个方法的参考页。