基于Java对于MongoDB数据库的复杂查询操作

Java基础

浏览数:88

2019-8-23

AD:资源代下载服务

前言

在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的复杂语句操作了。

基于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数据库的查询的复杂操作已经基本涵盖,希望可以帮助到各位。

作者:冘若烦