前言
在sql转noSql途中总是免不了一些对于原有的复杂sql语句的转译工作,因为不熟悉java环境下对于mongoDB操作的语句,所以走了不少的弯路,这些复杂语句在stackoverflow中找又会花上不少时间,于是在这里做个记录。
Java的配置并且连接MongoDB
- 首先在pom.xml文件中加入依赖包: “mongo-java-driver”(因为scala对于java的支持,所以这个driver就不作区分了),配置的代码如下:
<dependency> <groupId>org.mongodb</groupId> <artifactId>mongo-java-driver</artifactId> <version>3.4.2</version> </dependency>
- 连接Mongo Server以及collection的方法
- org.mongodb中提供了ServerAddress类用来储存连接mongo的ip地址以及端口,初始化的方法为:
private ServerAddress serverAddress = new ServerAddress("<ip地址>", "<端口>(这是个int)");
- 如果这个MongoDB的服务器是一个集群,那么通常来说需要设置setSlaveOK才能通过某一台服务器去访问数据,但是,我们可以把整个集群的服务器list输入给ServerAddress类,其初始化的方法为:
private MongoClient mongoClient = new MongoClient(Arrays.asList(new ServerAddress("<ip地址1>", "<端口>(这是个int)"), new ServerAddress("<ip地址2>", "<端口>(这是个int)"), new ServerAddress("<ip地址3>", "<端口>(这是个int)")));
- 如果这个mongoDB的数据库是有权限访问设置的数据库,则还需要MongoCredential类将数据库的 名称,用户名,密码传入连接数据库的方法中,其初始化的方法为:
private MongoCredential credential = MongoCredential.createCredential("<用户名>", "<数据库名称>", "<密码>");
- 最后才是连接MongoDB数据库的操作,使用的是MongoClient类,其初始化的方法为:(注意这里的credential变量需要转化为List类才能作为输入)
private MongoClient mongoClient = new MongoClient(serverAddress, Arrays.asList(credential));
- 如若要获取这个server下的某一个数据库(Database),则需要执行如下方法:
MongoDatabase mydb = mongoClient.getDatabase("<数据库名称>");
- 在mongoDB中,我们熟知的table被称为collection,所以如果要获得某个collection(表格),需要执行如下的方法:
MongoCollection myCollection = mydb.getCollection("<该数据库下collection的名字>");
至此,我们已经可以连接到MongoDB下的所有数据表格,下面就可以来看看基于java对于MongoDB的复杂语句操作了。
- org.mongodb中提供了ServerAddress类用来储存连接mongo的ip地址以及端口,初始化的方法为:
基于Java对于MongoDB数据库的复杂语句查询
- 基础准备
- 在对MongoDB执行复杂查询之前,我们先要了解一下在Mongo-Java-Driver中是如何储存查询结果的。其用于储存结果的类是MongoCursor, 其通过collection类的find方法获取查询结果并通过.iterator()方法返回该MongoCursor类,本质是一个类似于Iterator的对象,可以通过调用hasNext()与next()方法来遍历整个返回结果。
- 另一方面,MongoCursor中所储存的数据类型为Document,类似于Json的存储方式,可以通过google的Gson包将其映射为你想要的java对象,实现方式为:
private Gson gson = new Gson(); // 转换为对象 gson.fromJson(gson.toJson(<你所获得的Document对象>), <你需要转换的成为的对象>.class)
- Java对MongoDB的复杂语句查询操作
这里为了保证对sql选手亲和度(我本人也是从sql起步的),我会尽量把这里的一些查询翻译成sql中比较相似的操作。where分句
常用的判别符号
基于Java的MongoDB的查询语句如果需要指定where的条件,需要用到BasicDBObject类用于存储where分句中判别字段(列的名称),判别类型(等于,不等于,大于,小于)和用于判别的值。其基本的初始化方法为:BasicDBObject dbObject = new BasicDBObject("<判别类型>", "用于判别的值"); // 指定判别的字段 BasicDBObject identification = new BasicDBObject("<用于判别的字段(列的名字)>", dbObject) // Example: 取得大于等于某个时间点的所有数据库记录 BasicDBObject exObject = new BasicDBObject("time", new BasicDBObject("$gte", (from + " 00:00")))
常用判别符号有:
判别符号 意义 $eq 相等 $ne 不等于 $gte 大于等于 $gt 大于 $lte 小于等于 $lt 小于 在where分句中使用and和or等逻辑关联词
从上面的叙述中可以看到,我们可以用BasicDBObject对象来表示对某个字段(某列)做限制条件的查找。如果要将这些查询条件使用逻辑关联词连在一起,则我们需要使用List对象将这些要关联的条件语句(BasicDBObject对象)连接在一起,再在最外层用一个新的BasicDBObject对象封装这些用逻辑连词连在一起的BasicDBObject List。具体实现代码如下:// 使用List来连接需要用逻辑关联词串联起来的条件语句 List<DBObject> criteria = new ArrayList<>(); criteria.add(new BasicDBObject("time", new BasicDBObject("$gte", (from + " 00:00")))); criteria.add(new BasicDBObject("time", new BasicDBObject("$lte", (to + " 23:59")))); criteria.add(new BasicDBObject("idc_group", idcGroup)); // 使用and来连接这个list // 这里也可以使用"$or"字段表示"或"逻辑 BasicObject andConnection =new BasicDBObject("$and", criteria); // 之后使用find方法去找到符合这个where条件的记录。 MongoCursor<Document> tCursor = mydb.getCollection(table).find(new BasicDBObject("$and", criteria)).iterator();
聚合操作(Aggregation, Group By)
基于Java对于MongoDB数据库查询如果需要执行聚合操作,则需要从MongoCollection对象调用aggregate方法,并把所需要的条件串联为list并作为输入进入aggregate方法。常用的一些关键词有:关键词 意义 $match 相等,类似于where中的等于某值 $sort 排序 $limit 与mysql中的limit相同 具体的关键词操作请参照文档 http://www.runoob.com/mongodb/mongodb-aggregate.html
下面给出例子:// 目标:获取所有满足如下条件的数据: // 1. "date"字段满足某个值 // 2. 先通过orderName1降序,再通过orderName2降序 // 3. 获取的记录不超过10条 MongoCursor<Document> cursor = quality.aggregate(Arrays.asList( // "$match"用于筛选date匹配这个值的记录 new Document("$match", new Document("date", (int)(Integer.valueOf(timeInput[0] + timeInput[1] + timeInput[2])))), new BasicDBObject("$sort", new BasicDBObject(orderName1, -1)), new BasicDBObject("$sort", new BasicDBObject(orderName2, -1)), new BasicDBObject("$limit", 10) )).iterator();
值得一提的是,因为MongoDB自身数据结构存储方式的问题,其不支持对于两个collection进行join的操作。
至此,基于Java对MongoDB数据库的查询的复杂操作已经基本涵盖,希望可以帮助到各位。