MongoDB插入

时间:2020-02-23 14:40:51  来源:igfitidea点击:

今天,我们将研究MongoDB插入命令。
Mongo Client可用于将文档插入集合中。
我们还可以插入一系列文档,今天我们将研究与MongoDB插入相关的各种操作。

MongoDB插入

对于MongoDB插入示例,我使用的是MongoDB版本3.4.7和Java驱动程序版本3.5.0。
但是,这些也应与其他版本一起使用。
请注意,mongo Java驱动程序API在3.x版本中已完全更改,因此,如果您使用的是旧版2.x版本,则必须相应地修改代码。

使用Mongo Client插入MongoDB

这是一个简单的示例,其中我将一个文档插入Person集合。

hyman:mongodb hyman$mongo
MongoDB shell version v3.4.7
connecting to: mongodb://127.0.0.1:27017
MongoDB server version: 3.4.7
Welcome to the MongoDB shell.
For interactive help, type "help".
> use theitroad
switched to db theitroad
> show collections
> db.Persons.insert({name:"hyman",country:"San Franceco"})
WriteResult({ "nInserted" : 1 })
> show collections
Persons
> db.Persons.find()
{ "_id" : ObjectId("59a3d6bf03ca62436260d57a"), "name" : "hyman", "country" : "San Franceco" }
>

请注意,如果我们不提供主键(即_id),MongoDB会自动生成它,并将其存储为ObjectId对象。

还要检查它是否返回包含写入文档数的" WriteResult"对象。
如果该集合不存在,MongoDB将创建它。

用主键插入MongoDB

现在,我们提供mongodb文档的主键,并查看可能发生的不同情况。

MongoDB插入具有ID的单个文档

> db.Persons.insert({_id:123,name:"hyman",country:"San Franceco"})
WriteResult({ "nInserted" : 1 })
> db.Persons.find()
{ "_id" : ObjectId("53fc3dc9b1e38e3716f79113"), "name" : "hyman", "country" : "San Franceco" }
{ "_id" : 123, "name" : "hyman", "country" : "San Franceco" }
>

如果已经存储了提供的ID的对象该怎么办。

MongoDB插入文档重复键错误

> db.Persons.insert({_id:123,name:"David",country:"San Franceco"})
WriteResult({
	"nInserted" : 0,
	"writeError" : {
		"code" : 11000,
		"errmsg" : "insertDocument :: caused by :: 11000 E11000 duplicate key error index: theitroad.Persons.$_id_  dup key: { : 123.0 }"
	}
})
>

好了,从输出看来,WriteResult还提供了错误代码和与之相关的消息,请注意,插入的行返回为0。

MongoDB批量插入

现在,让我们尝试使用一个命令插入多个文档。

> db.Persons.insert([{name:"David"},{name:"Kumar"}])
BulkWriteResult({
	"writeErrors" : [ ],
	"writeConcernErrors" : [ ],
	"nInserted" : 2,
	"nUpserted" : 0,
	"nMatched" : 0,
	"nModified" : 0,
	"nRemoved" : 0,
	"upserted" : [ ]
})
>

因此,对于一系列文档,MongoDB插入操作将返回包含更多信息的" BulkWriteResult"。

让我们尝试插入ID为ID的文档数组。

> db.Persons.insert([{_id:100,name:"David"},{_id:101,name:"Kumar"}])
BulkWriteResult({
	"writeErrors" : [ ],
	"writeConcernErrors" : [ ],
	"nInserted" : 2,
	"nUpserted" : 0,
	"nMatched" : 0,
	"nModified" : 0,
	"nRemoved" : 0,
	"upserted" : [ ]
})
>

现在,让我们看看在数组中插入一个文档出错时会发生什么。

> db.Persons.insert(
... [{_id:102,name:"PK"},
... {_id:101,name:"Kumar"},
... {_id:103,name:"PK"}])
BulkWriteResult({
	"writeErrors" : [
		{
			"index" : 1,
			"code" : 11000,
			"errmsg" : "insertDocument :: caused by :: 11000 E11000 duplicate key error index: theitroad.Persons.$_id_  dup key: { : 101.0 }",
			"op" : {
				"_id" : 101,
				"name" : "Kumar"
			}
		}
	],
	"writeConcernErrors" : [ ],
	"nInserted" : 1,
	"nUpserted" : 0,
	"nMatched" : 0,
	"nModified" : 0,
	"nRemoved" : 0,
	"upserted" : [ ]
})
> db.Persons.find()
{ "_id" : ObjectId("53fc3dc9b1e38e3716f79113"), "name" : "hyman", "country" : "San Franceco" }
{ "_id" : 123, "name" : "hyman", "country" : "San Franceco" }
{ "_id" : ObjectId("53fc40d1b1e38e3716f79114"), "name" : "David" }
{ "_id" : ObjectId("53fc40d1b1e38e3716f79115"), "name" : "Kumar" }
{ "_id" : 100, "name" : "David" }
{ "_id" : 101, "name" : "Kumar" }
{ "_id" : 102, "name" : "PK" }
>

很明显,当任何文档插入失败,未插入任何其他记录时,操作将终止,并且我们会收到错误消息,清楚地表明是哪个记录引起了问题。

MongoDB大容量插入排序和writeConcern参数

如果我们要执行批量操作并希望稍后处理错误文档,可以使用ordered参数告诉MongoDB跳过错误文档该怎么办。

> db.Persons.insert( [{_id:102,name:"PK"}, {_id:101,name:"Kumar"}, {_id:103,name:"PK"}] ,{ordered:false})
BulkWriteResult({
	"writeErrors" : [
		{
			"index" : 0,
			"code" : 11000,
			"errmsg" : "insertDocument :: caused by :: 11000 E11000 duplicate key error index: theitroad.Persons.$_id_  dup key: { : 102.0 }",
			"op" : {
				"_id" : 102,
				"name" : "PK"
			}
		},
		{
			"index" : 1,
			"code" : 11000,
			"errmsg" : "insertDocument :: caused by :: 11000 E11000 duplicate key error index: theitroad.Persons.$_id_  dup key: { : 101.0 }",
			"op" : {
				"_id" : 101,
				"name" : "Kumar"
			}
		}
	],
	"writeConcernErrors" : [ ],
	"nInserted" : 1,
	"nUpserted" : 0,
	"nMatched" : 0,
	"nModified" : 0,
	"nRemoved" : 0,
	"upserted" : [ ]
})
> db.Persons.find()
{ "_id" : ObjectId("53fc3dc9b1e38e3716f79113"), "name" : "hyman", "country" : "San Franceco" }
{ "_id" : 123, "name" : "hyman", "country" : "San Franceco" }
{ "_id" : ObjectId("53fc40d1b1e38e3716f79114"), "name" : "David" }
{ "_id" : ObjectId("53fc40d1b1e38e3716f79115"), "name" : "Kumar" }
{ "_id" : 100, "name" : "David" }
{ "_id" : 101, "name" : "Kumar" }
{ "_id" : 102, "name" : "PK" }
{ "_id" : 103, "name" : "PK" }
>

类似地,我们也可以为不同级别的关注点传递writeConcern参数,默认的写关注点被确认。
我们将在以后的文章中进行研究。

MongoDB插入Java示例

现在,让我们看看使用Java驱动程序在MongoDB集合中执行插入操作的不同方法。
请注意,这些Java程序使用的是mongo-java-driver版本3.5.0。

  • MongoDB插入单个文档的示例

一个简单的程序,使用MongoCollection.insertOne方法插入单个文档。

package com.theitroad.mongodb.main;

import java.net.UnknownHostException;

import org.bson.Document;

import com.mongodb.MongoClient;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;

public class MongoDBInsertExample {

	public static void main(String[] args) throws UnknownHostException {

		MongoClient mongo = new MongoClient("localhost", 27017);
		MongoDatabase db = mongo.getDatabase("theitroad");

		MongoCollection<Document> col = db.getCollection("Persons");

		Document document = new Document();
		document.append("name", "hyman");
		document.append("country", "USA");

		col.insertOne(document);

		System.out.println("ID Generated=" + document.getObjectId("_id").toString());
		mongo.close();
	}

}

下图显示了生成的输出,请注意生成的ID正在打印到控制台。

我们还可以像下面那样传递我们自己的id参数。

document.append("_id",new ObjectId("123456789012".getBytes())); //min byte array length should be 12
document.append("_id", new ObjectId(new Date())); //ObjectId constructor also takes Date as argument

但是,如果我们试图通过传递一些参数来创建ObjectId实例,例如document.append(" _ id",new ObjectId(" 1234"));,它将抛出以下异常。

Exception in thread "main" java.lang.IllegalArgumentException: invalid hexadecimal representation of an ObjectId: [1234]
	at org.bson.types.ObjectId.parseHexString(ObjectId.java:549)
	at org.bson.types.ObjectId.<init>(ObjectId.java:239)
	at com.theitroad.mongodb.main.MongoDBInsertExample.main(MongoDBInsertExample.java:24)

这是因为在为ObjectId传递参数时已经进行了一些验证,因此传递的String应该是十六进制字符串。
您可以查看其源代码以获取更多详细信息。

如果您尝试传递ObjectId,例如document.append(" _ id",new ObjectId(" 1234" .getBytes());,则会引发以下异常。

Exception in thread "main" java.lang.IllegalArgumentException: state should be: buffer.remaining() >=12
	at org.bson.assertions.Assertions.isTrueArgument(Assertions.java:62)
	at org.bson.types.ObjectId.<init>(ObjectId.java:272)
	at org.bson.types.ObjectId.<init>(ObjectId.java:249)
	at com.theitroad.mongodb.main.MongoDBInsertExample.main(MongoDBInsertExample.java:33)

原因是字节数组的最小大小应为12。

  • MongoDB插入Map Java程序

如果您查看上面的"文档"示例,就会发现它与Map非常相似。
我们可以轻松地将Map插入为文档,示例代码段如下所示。

Map<String,Object> dataMap = new HashMap<String,Object>();
dataMap.put("name", "hyman");
dataMap.put("country", "USA");
dataMap.put("_id",new ObjectId("123459789012".getBytes()));

Document document = new Document(dataMap);
		
col.insertOne(document);
  • MongoDB插入JSON文档

有时我们会得到JSON响应,主要是在调用Web服务时。
因此,MongoDB提供了一种简单的方法来在MongoDB集合中插入JSON文档,如下面的示例所示。

String json = "{ 'name' : 'hyman', 'country' : 'USA' }";
Document document = Document.parse(json);

col.insertOne(document);
  • 插入多个文件

我们也可以使用Mongo Java驱动程序插入多个文档,下面显示一个简单的示例。

package com.theitroad.mongodb.main;

import java.util.ArrayList;
import java.util.List;

import org.bson.Document;

import com.mongodb.MongoClient;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;

public class MongoDBInsertMultipleExample {

	public static void main(String[] args) {
		MongoClient mongo = new MongoClient("localhost", 27017);
		MongoDatabase db = mongo.getDatabase("theitroad");

		MongoCollection<Document> col = db.getCollection("Persons");
		
		List<Document> docs = new ArrayList<>();
		docs.add(new Document("name", "hyman"));
		docs.add(new Document().append("name", "David"));
		
		col.insertMany(docs);
		
		for(Document doc : docs) {
			System.out.println("Name="+doc.getString("name")+", ID="+doc.getObjectId("_id").toString());
		}
		mongo.close();
	}

}

产生的输出将如下所示。

Name=hyman, ID=59a404c9c5130d39760a01a2
Name=David, ID=59a404c9c5130d39760a01a3