MongoDb的接口使用(Java版本)

本文将介绍MongoDB的使用,主要有:

  • MongoDB的简介以及导入样例数据;
  • Java Driver的概览;
  • 基本的CRUD操作和数据聚合( Aggregation);
  • 创建索引以提高查询性能。

1.MongoDB的简介以及导入样例数据

MongoDB是一个提供高性能的文档数据库(document database),它通过消除对对象关系模型(ORM)的刚性需求从而促进开发。

Documents:document是指MongoDB中的记录,由field和value对组成。MongoDB中的document与JSON对象相类似。fields对应的values可以包含其他的document,数组document数组。

Collections:在MongoDB中,document是存储在Collections(集合)中的,Collections类似于关系型数据库中的table,但又不是table,因为Collection并不需要它的document拥有同样的模式(schema),如下表示一个restaurants collection:

{
  "address": {
     "building": "1007",
     "coord": [ -73.856077, 40.848447 ],
     "street": "Morris Park Ave",
     "zipcode": "10462"
  },
  "borough": "Bronx",
  "cuisine": "Bakery",
  "grades": [
     { "date": { "$date": 1393804800000 }, "grade": "A", "score": 2 },
     { "date": { "$date": 1378857600000 }, "grade": "A", "score": 6 },
     { "date": { "$date": 1358985600000 }, "grade": "A", "score": 10 },
     { "date": { "$date": 1322006400000 }, "grade": "A", "score": 9 },
     { "date": { "$date": 1299715200000 }, "grade": "B", "score": 14 }
  ],
  "name": "Morris Park Bake Shop",
  "restaurant_id": "30075445"
}

2.导入样例数据

a)准备一份数据并命名为primer-dataset.json,如附件所示。

b)将数据导入collection

在命令行或者shell终端,使用mongoimport将准备好的document插入test数据库中的restaurant collection中。

cd /Users/young/Desktop/MongoDB
mongoimport --db test --collection restaurants --drop --file primer-dataset.json

如果test中已经存在restaurant collection,该操作将首先会drop掉restaurant collection。

mongoimport 默认连接上一个运行在本地的默认端口为27017的mongod实例。如果需要将数据导入其他的MongoDB,需要使用--host 和 --port 指出主机名和端口号。

3.Java Driver的概览

MongoDB的Java Driver是官方支持的。

a)下载MongoDB的Java驱动和BSON库文件。

http://mongodb.github.io/mongo-java-driver/?_ga=1.254442379.2073848550.1463710724

b)连接到MongoDB

使用com.mongodb.MongoClient类可以连接到运行的mongod实例。可以使用 com.mongodb.client.MongoDatabase接口访问一个指定的MongoDB数据库。

import com.mongodb.MongoClient;
import com.mongodb.client.MongoDatabase;
MongoClient mongoClient = new MongoClient();
MongoDatabase db = mongoClient.getDatabase("test");

 4.调用Java驱动实现CRUD功能

 a)插入数据

你可以使用insertOne方法将一个document插入到MongoDB的指定的collection中,如果这个collection不存在,MongoDB将会自动创建该collection并执行操作。

import com.mongodb.client.MongoDatabase;
import org.bson.Document;
import java.text.DateFormat;
import java.text.ParseException;
public void insertDocument(MongoDatabase db, String collection, Document document) throws ParseException {
		// DateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'",
		// Locale.ENGLISH);
		db.getCollection(collection).insertOne(document);
	}

 这段代码将document插入db.collection中,定义document,可以使用 org.bson.Document :

new Document("address",
                new Document()
                        .append("street", "2 Avenue")
                        .append("zipcode", "10075")
                        .append("building", "1480")
                        .append("coord", asList(-73.9557413, 40.7720266)))
                .append("borough", "Manhattan")
                .append("cuisine", "Italian")
                .append("grades", asList(
                        new Document()
                                .append("date", format.parse("2014-10-01T00:00:00Z"))
                                .append("grade", "A")
                                .append("score", 11),
                        new Document()
                                .append("date", format.parse("2014-01-16T00:00:00Z"))
                                .append("grade", "B")
                                .append("score", 17)))
                .append("name", "Vella")
                .append("restaurant_id", "41704620")
 执行插入操作不返回任何结果。如果传递给insertOne的document不包含_id  field,Java驱动将会自动增加该field并使用该_id对应的值生成对象id(ObjectId)。插入多个document可以使用 insertMany方法。

b)检索数据

你可以使用find方法发布一个查询从MongoDB中检索数据。在MongoDB中,所有的所有的查询是在一个单独的collection中。查询操作可以返回指定collection中所有的document或者匹配 org.bson.Document定义的过滤标准的document。

public FindIterable<Document> FindCollection(MongoDatabase db, String collection, Document document) {
		FindIterable<Document> iterator = null;
		if (null == document)
			iterator = db.getCollection(collection).find();
		else
			iterator = db.getCollection(collection).find(document);
		return iterator;
	}

find方法返回一个生成document的 FindIterable的迭代器对象。

 FindIterable<Document> iterator=mongoDBInstance.FindCollection(db,
		 collection, null);
		iterator.forEach(new Block<Document>(){
	
		 @Override
		 public void apply(final Document document) {
		 System.out.println(document);
		 }
		
		 });
 使用MongoDB的Java Driver,用如下的的方式相等:
new Document( <field>, <value> )

如果 <field>是嵌套的,使用点记法访问。Java Driver同事提供了com.mongodb.client.model.Filters描述查询条件,该类提供了很多静态方法方便地创建插叙判断,如eq方法:

eq(<field>, <value>)//等于
lt(<field>, <value>)//小于
gt(<field>, <value>)//大于
 查询没有嵌套层的Field:
FindIterable<Document> iterable = mongoDBInstance.getCollection("restaurants").find(
        new Document("borough", "Manhattan"));
 或者使用Filters:
FindIterable<Document> iterable = mongoDBInstance.getCollection("restaurants").find(
        eq("borough", "Manhattan"));
 查询一个嵌套的Field:
FindIterable<Document> iterable = mongoDBInstance.getCollection("restaurants").find(
        eq("address.zipcode", "10075"));
 查询一个数组中的Field:
FindIterable<Document> iterable=mongoDBInstance.getCollection("restaurants").find(eq("grades.grade", "B"));
 c)更新document

可以使用 updateOne 、 updateMany、replaceOne方法更新collection中的document,这些方法都接受如下三种参数:

  • filtes描述的document匹配规则
  • 指定修改部分的document
  • 其他可选的参数

需要注意的是_id这个Field是不可以被更新的。

1)更新顶级的Fields

如下代码更新了第一个name是Juni的document,用$set操作更新了cuisine为American (New),同时(append)用$currentDate操作更新了lastModified为当前时间。

mongoDBInstance.getCollection("restaurants").updateOne(new Document("name", "Juni"),
        new Document("$set", new Document("cuisine", "American (New)"))
            .append("$currentDate", new Document("lastModified", true)));
 2)更新嵌套的Field 如下更新了嵌套在address中的street这个Field:
mongoDBInstance.getCollection("restaurants").updateOne(new Document("restaurant_id", "41156888"),
        new Document("$set", new Document("address.street", "East 31st Street")));
 updateOne方法返回一个UpdateResult对象,这个对象包含了本次操作的一些信息。如UpdateResult.getModifiedCount()返回这次更新的document的数量。 3)同时更新多个document 更新多个document,使用updateMany方法。如下操作将更新address.zipcode等于10016,并且cuisine等于Other的所有document。
mongoDBInstance.getCollection("restaurants").updateMany(new Document("address.zipcode", "10016").append("cuisine", "Other"),
        new Document("$set", new Document("cuisine", "Category To Be Determined"))
                .append("$currentDate", new Document("lastModified", true)));
 updateMany方法返回一个UpdateResult对象,这个对象包含了本次操作的一些信息。如UpdateResult.getModifiedCount()返回这次更新的document的数量。 4)document的替换 替换整个文档(不包含_id),需要传递一个完整的新的document给 replaceOne的第二个参数。替换的document可以有与原document不一样的Field。前者可以省略掉_id因为它是不可以改变的。如果您的新document包含_id,必须确保其与原document具有相同的值。
mongoDBInstance.getCollection("restaurants").replaceOne(new Document("restaurant_id", "41704620"),
        new Document("address",
                new Document()
                        .append("street", "2 Avenue")
                        .append("zipcode", "10075")
                        .append("building", "1480")
                        .append("coord", asList(-73.9557413, 40.7720266)))
                .append("name", "Vella 2"));
 replaceOne操作也返回一个UpdateResult对象,这个对象包含了本次操作的一些信息。如UpdateResult.getModifiedCount()返回这次更新的document的数量。 d)删除数据 从collection中删除document可以使用deleteOne和deleteMany方法。方法中需要携带一个条件用以决定哪个document需要被删除。指定这样一个document的方法跟查询操作的一样。
mongoDBInstance.getCollection("restaurants").deleteMany(new Document("borough", "Manhattan"));
mongoDBInstance.getCollection("restaurants").deleteMany(new Document());
mongoDBInstance.getCollection("restaurants").drop();
 第一行代码将会删除restaurant中borough为Manhattan的所有document,第二行代码将会删除restaurant中的所有document,但是restaurant本身以及在其上建立的索引,均不会被删除,第三行代码将会达到这种效果。 在MongoDB中写是一个原子操作,这就意味着删除操作可以和其他写操作交替进行。 e)数据聚集 MongoDB可以执行聚集操作,如根据一个指定的key分组、评估总数以及给定组的数量。 根据Field分组以及评估数量
AggregateIterable<Document> iterable = mongoDBInstance.getCollection("restaurants").aggregate(asList(
        new Document("$match", new Document("borough", "Queens").append("cuisine", "Brazilian")),
        new Document("$group", new Document("_id", "$address.zipcode").append("count", new Document("$sum", 1)))));
 聚集操作是根据指定field的value进行。 f)索引 索引可以提高查询的效率。若没有索引,MongoDB的查询将会是在整个collection中进行一遍扫描,从而找出匹配查询条件的document。如果从在合适的索引,MongoDB可以使用索引限制检索document的数量。 在collection上创建索引使用 createIndex 方法。collection一旦创建,MongoDB将会自动在_id字段创建索引。 在field上或者fields上创建索引,需要用org.bson.Document指定需要创建索引的fields以及索引类型,并将它传给createIndex方法。
new Document(<field1>, <type1>).append(<field2>, <type2>) ...
 type为1:升序 type为-1:降序 1)在单个Field上创建索引
mongoDBInstance.getCollection("restaurants").createIndex(new Document("cuisine", 1));
  2)创建混合索引
mongoDBInstance.getCollection("restaurants").createIndex(new Document("cuisine", 1).append("address.zipcode", -1));
 创建索引的操作没有返回结果。

猜你喜欢

转载自worldly.iteye.com/blog/2299716