mongodb dirver for java【读取操作】

41 篇文章 1 订阅

环境

MongoDB:3.0+
mongodb dirver for java: 3.4
@author:喻涛

概要

本篇是翻译官网:
https://mongodb.github.io/mongo-java-driver/3.4/driver/tutorials/perform-read-operations/

讲解的是用java代码对MongoDB进行读操作。

Find Operations 查询操作

查询操作是从集合中检索文档。你可以指定过滤器,去选择只匹配过符合滤条件的文档。

先决条件

test数据库中要有一个restaurants集合。
(你可以使用你本地的测试环境中的集合,来做下面的测试)

可能需要import的声明:

 import com.mongodb.*;
 import com.mongodb.MongoClient;
 import com.mongodb.client.MongoCollection;
 import com.mongodb.client.MongoDatabase;
 import com.mongodb.client.model.Projections;
 import com.mongodb.client.model.Filters;
 import static com.mongodb.client.model.Filters.*;
 import static com.mongodb.client.model.Projections.*;
 import com.mongodb.client.model.Sorts;
 import java.util.Arrays;
 import org.bson.Document;

下面的这段代码是在教程示例中将会打印查询操作的结果。

Block<Document> printBlock = new Block<Document>() {
       @Override
       public void apply(final Document document) {
           System.out.println(document.toJson());
       }
};

连接数据库

这里我贴出我自己的代码:

            //连接数据库 start
            MongoCredential credential = 
            //根据自己的情况修改
            MongoCredential.createCredential("gg_openapi", 
            "gg_openapi", "gg..openapi#!".toCharArray());
            //根据自己的情况修改
            serverAddress = new ServerAddress("106.75.51.20", 35520);
            List<ServerAddress> addrs = new ArrayList<ServerAddress>();
            addrs.add(serverAddress);
            List<MongoCredential> credentials = new ArrayList<MongoCredential>();
            credentials.add(credential);
            @SuppressWarnings("resource")
            MongoClient mongoClient = new MongoClient(addrs, credentials);
            MongoDatabase database = mongoClient.getDatabase("gg_openapi");
            System.out.println("Connect to database successfully");
            //连接数据库 end

对集合进行查询

对集合进行查询,你可以使用find()方法。

你可以在集合中调用这个方法,不传参数就是查询全部的文档。

collection.find().forEach(printBlock);

或者传入一个过滤器来查询符合过滤标准的文档。

collection.find(eq("name", "456 Cookies Shop"))
            .forEach(printBlock);

查询 过滤器

要查询符合特定条件的文档,可以给find()方法,传入一个过滤器文档。
(可能看着很拗口,看看下面就明白啦)

空过滤器

要指定一个空过滤器(这样做的话,就是查询全部文档),使用空的Document对象。

collection.find(new Document()).forEach(printBlock);

当然你也可以用更简单的写法:

collection.find().forEach(printBlock);

Filters 助手

为了方便的创建过滤器文档,java驱动提供了Filters类,这个类提供有很多过滤条件的方法。

假设现在我们有这样一些需求:
①字段stars大于等于2并且小于5
categories字段等于Bakery(如果categories是个数组,那就是包含Bakery)。

collection.find(
    new Document("stars", new Document("$gte", 2)
          .append("$lt", 5))
          .append("categories", "Bakery")).forEach(printBlock);

以下示例是使用Filters助手指定相同过滤条件:

collection.find(and(gte("stars", 2), lt("stars", 5), eq("categories", "Bakery"))).forEach(printBlock);

关于MongoDB过滤查询列表,可以参考MongoDB Manual,有关Filters助手可以查看Filters
另请参考在MongoDB查询概述中的Query Documents Tutorial,包括在数组和嵌套文档中指定过滤条件。

FindIterable

find()方法会返回FindIterable接口的一个实例。这个接口提供了各种方法,你可以链接到find()方法改变输出和查询的行为,例如:sort()projection(),以及对结果的遍历,例如:iterator()forEach()

Projections

默认情况下,在MongoDB查询匹配文档中返回全部字段。要在匹配的文档中返回指定字段,你需要指定projection document

下面的find操作中包含一个projection其要插入Document对象,该对象是用来指定返回匹配的文档字段为:namestarscategories

collection.find(and(gte("stars", 2), 
                    lt("stars", 5), 
                    eq("categories", "Bakery")))
          .projection(new Document("name", 1)
                     .append("stars", 1)
                     .append("categories",1)
                     .append("_id", 0))
          .forEach(printBlock);

为了方便创建projection文档,java驱动提供了Projections类。

collection.find(and(gte("stars", 2), 
                    lt("stars", 5), 
                    eq("categories", "Bakery")))
          .projection(fields(include("name", "stars", 
                                     "categories"), 
                                     excludeId()))
          .forEach(printBlock);

projection文档(这里的文档你可以理解对Document对象)中,你也可以使用projection操作符指定projection表达式。

有关使用Projections.metaTextScore的示例,可以参考Text Search tutorial.

sorts

要排序文档,可以把排序规范的文档(这里的文档你可以理解对Document对象)传递给FindIterable.sort()方法。

java驱动程序也提供了Sorts助手来方便我们进行排序操作。

collection.find(and(gte("stars", 2), 
                    lt("stars", 5), 
                    eq("categories","Bakery")))
          .sort(Sorts.ascending("name"))
          .forEach(printBlock);

Sort with Projections

FindIterable方法本身就返回FindIterable对象。因此,你可以应用多个FindIterable方法在find()方法中。

collection.find(and(gte("stars", 2), 
                    lt("stars", 5), 
                    eq("categories", "Bakery")))
          .sort(Sorts.ascending("name"))
          .projection(fields(include("name", 
                                     "stars", 
                                     "categories"),excludeId()))
          .forEach(printBlock);

MongoIterable

MongoIterable提供了帮助方法来访问操作结果:

iterator()
first()
forEach()
map()
into()

读取偏好 Read Preference

对于复制集分片集群的读取操作,应用程序可以在三个层次中对read Preference进行配置。

一、 In a MongoClient()
①通过MongoClientOptions:

  MongoClientOptions options = MongoClientOptions.builder()
                              .readPreference(ReadPreference.secondary())
                              .build();
  MongoClient mongoClient = new MongoClient(Arrays.asList(
                                  new ServerAddress("host1", 27017),
                                  new ServerAddress("host2", 27017)), options);

②通过MongoClientURI,如下所示:

MongoClient mongoClient = new MongoClient(
new MongoClientURI("mongodb://host1:27017,host2:27017/?readPreference=secondary"));

二、In a MongoDatabase

通过 withReadPreference 方法。

MongoDatabase database = mongoClient.getDatabase("test")
                         .withReadPreference(ReadPreference.secondary());

三、In a MongoCollection
通过withReadPreference方法:

MongoCollection<Document> collection= database.getCollection("restaurants")
                           .withReadPreference(ReadPreference.secondary());

MongoDatabaseMongoCollection实例是不可变的。
在已存在的MongoDatabaseMongoCollection实例中调用withReadPreference()方法会返回一个新的实例并不影响调用该方法的实例。

例如,下面代码,collectionWithReadPref实例有个read preferenceprimaryPreferredcollectionread preference是不是影响的。

MongoCollection<Document> collectionWithReadPref = 
collection.withReadPreference(ReadPreference.primaryPreferred());
//collection的read preference是不受影响的

Read Concern

对于复制集分片集群的读取操作,应用程序可以在三个层次中对read concern进行配置。

一、在MongoClient()

①通过MongoClientURI,如下所示:

MongoClient mongoClient = new MongoClient(
new MongoClientURI("mongodb://host1:27017,host2:27017/?readConcernLevel=majority"));

②通过MongoClientOptions,如下所示:

MongoClientOptions options = MongoClientOptions.builder().readConcern(ReadConcern.DEFAULT).build();
MongoClient mongoClient = new MongoClient(Arrays.asList(
                              new ServerAddress("host1", 27017),
                              new ServerAddress("host1", 27017)), options);

二、在MongoDatabase

通过withReadConcern方法,如下所示:

MongoDatabase database = mongoClient.getDatabase("test")
                                    .withReadConcern(ReadConcern.DEFAULT);

三、在MongoCollection

通过withReadConcern方法,如下所示:

MongoCollection<Document> collection = 
database.getCollection("restaurants").withReadConcern(ReadConcern.DEFAULT);

你可以构建MongoClientOptionsMongoDatabase或者MongoCollection,来包含read concernread preferencewrite concern的组合。

例如:下面的集合中包含了上面全部的三种情况。

collection = database.getCollection("restaurants")
                     //read preference
                     .withReadPreference(ReadPreference.primary())
                     //read concern
                     .withReadConcern(ReadConcern.MAJORITY)
                     //write concern
                     .withWriteConcern(WriteConcern.MAJORITY);

总结

1、最后面的几种配置,我们平时用不到。

2、新的驱动提供了Filters类,这样以后就可以不用写诸如下面这样的代码:

Document document = new Document();
document.append("categories", "Bakery");

虽然诸如:andgtelt等这样的helper方法可以使代码简洁;
但是我还是建议使用创建Document的方法。因为它使用的是MongoDB本身的操作符;
这样的好处,就是方便你不断强化记住MongoDB原始的操作符;
这样你在MongoDB客户端中写查询语句也不会很陌生。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

山鬼谣me

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值