基于 MongoTemplate实现MongoDB的复杂查询功能

 更新时间:2024年12月04日 08:55:18   作者:算死草  
本文介绍了如何使用MongoTemplate进行复杂的MongoDB查询,展示了如何进行分页和排序查询,通过示例代码,展示了如何处理不同类型的查询,如单条件查询、模糊查询、组合条件查询以及分页排序查询,感兴趣的朋友跟随小编一起看看吧

MongoDB是典型的非关系型数据库,但是它的功能越来越复杂,很多项目中,我们为了快速拓展,甚至直接使用Mongo 来替代传统DB做数据持久化。
虽然MongoDB在支持具体业务时没有问题,但是由于它是文档型数据库,拥有一套独立的语法,不再支持传统的SQL。
开发人员发现在实际开发过程中,由于语法问题,在处理复杂的业务查询时,不知该如何下手,使不上劲。
在这里我总结了一下接触到的使用场景:
如果是简单的业务,那么我们直接使用spring JPA来实现就可以,比如这些操作:
1、创建
2、删除
3、修改
4、简单的查询
因为这些语句的逻辑往往不是很复杂,JPA完全可以胜任,而且还清晰直观。
如果是复杂的场景,我们就使用MongoTemplate 来组织条件逻辑:
假设背景是有张Student 表,结构如下:
我们已经预先插入了下边的数据:

(1)先来一个简单的单条件查询:

private void simpleInQuery() {
         Query query = new Query();
         query.addCriteria(Criteria.where("classNo").ne(2));
         List<Student> students = mongoTemplate.find(query, Student.class);
         log.warn("the query result is: {}", students);
     }

输出如下:

14:39:19.805  WARN 83348 --- [           main] c.e.demo.learn.mongo.MongodbController   : the query result is: 
[Student(_id=674d8125bf8e9e35bbc08718, name=xiaoa, description=good1, classNo=1, age=15), 
Student(_id=674d8125bf8e9e35bbc08719, name=xiaob, description=good2, classNo=1, age=13), 
Student(_id=674d8125bf8e9e35bbc0871a, name=xiaoc, description=good3, classNo=1, age=15),Student(_id=674d8125bf8e9e35bbc0871b, name=xiaod, description=good4, classNo=1, age=15), 
Student(_id=674d8153c993425aaa5c4fec, name=zhongd, description=perfect2, classNo=3, age=15), 
Student(_id=674d81dc8130705614f23311, name=biga, description=nice, classNo=3, age=15), 
Student(_id=674d81dd8130705614f23312, name=bigb, description=nice, classNo=3, age=13), 
Student(_id=674d81dd8130705614f23313, name=bigc, description=nice, classNo=3, age=15), 
Student(_id=674d81dd8130705614f23314, name=bigd, description=nice, classNo=3, age=15)]

观察代码,我们发现需要首先创建一个Query 实例,表示是一个查询动作。query 对象,继续补充一个Criteria 实例。Criteria 英[kraɪ'tɪəriə] 译为比标准、准则、尺度。我们可以直接理解为查询条件。注意Criteria 实例是由 Criteria.where 方法创建出来的。(防盗连接:本文首发自http://www.cnblogs.com/jilodream/ )这是一个简单工厂,参数为要查询的表的列名(文档的字段)。再跟一个in() ,表示列的in 操作,in() 中跟的是in操作的值。最后直接用mongoTemplate 实例执行find 操作就好,条件为查询逻辑和表对应的类文件。我们这里使用的是in 操作,除此之外,常用的还有

方法作用类比sql
gt表示 大于>
gte表示 大于等于 >=
lt 表示 小于<
lte 表示 小于等于 <=
ne 表示 不等于 !=
nin 表示 不属于 not in
is 表示等于 =

regex

 表示 like (注意后面跟正则表达式,如 "^.*" + queryKeyWord + ".*$")like ‘%关键字%’

这些都是基本操作,有sql经验的同学肯定明白具体怎么使用。
我们再补充一个模糊查询的例子:

private void simpleRegexQuery() {
        Query query = new Query();
        String queryKeyWord = "ong";
        query.addCriteria(Criteria.where("name").regex("^.*" + queryKeyWord + ".*$"));
        List<Student> students = mongoTemplate.find(query, Student.class);
        log.warn("the query result is: {}", students);
    }

输出如下:

2024-12-03 14:46:23.781  WARN 81708 --- [           main] c.e.demo.learn.mongo.MongodbController   : the query result is: 
[Student(_id=674d8152c993425aaa5c4fe9, name=zhonga, description=perfect2, classNo=2, age=15), 
Student(_id=674d8153c993425aaa5c4fea, name=zhongb, description=perfect2, classNo=2, age=13), 
Student(_id=674d8153c993425aaa5c4feb, name=zhongc, description=perfect2, classNo=2, age=15), 
Student(_id=674d8153c993425aaa5c4fec, name=zhongd, description=perfect2, classNo=3, age=15)]

(2)接着来看一个相对复杂点的组合条件:两个或条件,类似于SQL中的: A表达式 OR B表达式,代码如下

private void simpleOrQuery() {
        Query query = new Query();
        String queryKeyWord = "ong";
        Criteria neCri = Criteria.where("age").ne(15);
        Criteria regexCri = Criteria.where("name").regex("^.*" + queryKeyWord + ".*$");
        Criteria orCri = new Criteria().orOperator(neCri, regexCri);
        query.addCriteria(orCri);
        List<Student> students = mongoTemplate.find(query, Student.class);
        log.warn("the query result is: {}", students);
    }

执行效果如下:

2024-12-03 14:48:28.787  WARN 83804 --- [           main] c.e.demo.learn.mongo.MongodbController   : the query result is: 
[Student(_id=674d8125bf8e9e35bbc08719, name=xiaob, description=good2, classNo=1, age=13), 
Student(_id=674d8152c993425aaa5c4fe9, name=zhonga, description=perfect2, classNo=2, age=15), 
Student(_id=674d8153c993425aaa5c4fea, name=zhongb, description=perfect2, classNo=2, age=13),
 Student(_id=674d8153c993425aaa5c4feb, name=zhongc, description=perfect2, classNo=2, age=15), 
Student(_id=674d8153c993425aaa5c4fec, name=zhongd, description=perfect2, classNo=3, age=15), 
Student(_id=674d81dd8130705614f23312, name=bigb, description=nice, classNo=3, age=13)]

我们创建好两个Criteria的简单条件之后,再创建一个新的Criteria 实例,用一个or操作将二者关联起来.
query 接收最新的Criteria 实例,然后执行查询即可。
这里的写法类似于sql中的
where name like "%ong%" or age != 15

如果是两个AND 条件,类似于SQL中的: (防盗连接:本文首发自http://www.cnblogs.com/jilodream/ )A表达式 AND B表达式,用法和or的使用方法是一样的 。这里就不举例了,
我们这里写一个复杂的用法:

private void complexQuery() {
        Query query = new Query();
        String queryKeyWord = "ong";
        Criteria ageCri = Criteria.where("age").ne(15);
        Criteria nameCri = Criteria.where("name").regex("^.*" + queryKeyWord + ".*$");
        Criteria cri1 = new Criteria().orOperator(ageCri, nameCri);
        Criteria descCri = Criteria.where("description").is("nice");
        Criteria classNoCri = Criteria.where("classNo").in(1, 2, 3);
        Criteria cri2 = new Criteria().andOperator(descCri, classNoCri);
        query.addCriteria(new Criteria().orOperator(cri1, cri2));
        List<Student> students = mongoTemplate.find(query, Student.class);
        log.warn("the query result is: {}", students);
    }

输出如下:

2024-12-03 14:51:46.908  WARN 92840 --- [           main] c.e.demo.learn.mongo.MongodbController   : the query result is: 
[Student(_id=674d8125bf8e9e35bbc08719, name=xiaob, description=good2, classNo=1, age=13), 
Student(_id=674d8152c993425aaa5c4fe9, name=zhonga, description=perfect2, classNo=2, age=15), 
Student(_id=674d8153c993425aaa5c4fea, name=zhongb, description=perfect2, classNo=2, age=13), 
Student(_id=674d8153c993425aaa5c4feb, name=zhongc, description=perfect2, classNo=2, age=15), 
Student(_id=674d8153c993425aaa5c4fec, name=zhongd, description=perfect2, classNo=3, age=15), 
Student(_id=674d81dc8130705614f23311, name=biga, description=nice, classNo=3, age=15), 
Student(_id=674d81dd8130705614f23312, name=bigb, description=nice, classNo=3, age=13), 
Student(_id=674d81dd8130705614f23313, name=bigc, description=nice, classNo=3, age=15),
 Student(_id=674d81dd8130705614f23314, name=bigd, description=nice, classNo=3, age=15)](防盗连接:本文首发自http://www.cnblogs.com/jilodream/ )

这里的写法类似于sql中的

where ( description = "nice" and classNo in (1 ,2 ,3) ) or ("name like %ong%" or age != 15)

总体来看:一个Criteria 实例,就是一个查询条件。

我们可以通过 or、and 操作来不断的组合生成一个新的Criteria实例,也就是一个新的查询条件 ,并且可以以此查询条件继续组合生成更高级的Criteria,以此不断的类推。

这个过程就像垒积木一样:

(3) 接着我们整合下分页功能,并且以班级排序

PageRequest pageable = PageRequest.of(pageIndex - 1, pageSize);
Query pageQuery=query.with(pageable).with(Sort.by(Sort.Direction.DESC,"classNo"));

注意分页时,页码数是从0开始,所以要-1。同时排序使用Sort生成sort的对象,包含排序方式和字段,并且这里支持多级排序。

整体代码如下:

private void complexPageQuery() {
        int pageIndex=2;
        int pageSize=3;
        Query query = new Query();
        String queryKeyWord = "ong";
        Criteria ageCri = Criteria.where("age").ne(15);
        Criteria nameCri = Criteria.where("name").regex("^.*" + queryKeyWord + ".*$");
        Criteria cri1 = new Criteria().orOperator(ageCri, nameCri);
        Criteria descCri = Criteria.where("description").is("nice");
        Criteria classNoCri = Criteria.where("classNo").in(1, 2, 3);
        Criteria cri2 = new Criteria().andOperator(descCri, classNoCri);
        query.addCriteria(new Criteria().orOperator(cri1, cri2));
        long allDataSize = mongoTemplate.count(query, Student.class);
        PageRequest pageable = PageRequest.of(pageIndex - 1, pageSize);
        Query pageQuery=query.with(pageable).with(Sort.by(Sort.Direction.DESC,"classNo"));
        List<Student> students = mongoTemplate.find(pageQuery, Student.class);
        log.warn("the query result is: {}", students);
    }

输出如下:

2024-12-03 14:56:46.059  WARN 18516 --- [           main] c.e.demo.learn.mongo.MongodbController   : the query result is: 
[Student(_id=674d81dd8130705614f23314, name=bigd, description=nice, classNo=3, age=15),
 Student(_id=674d81dc8130705614f23311, name=biga, description=nice, classNo=3, age=15), 
Student(_id=674d8152c993425aaa5c4fe9, name=zhonga, description=perfect2, classNo=2, age=15)]

到此这篇关于基于 MongoTemplate 实现MongoDB的复杂查询的文章就介绍到这了,更多相关基于 MongoTemplate 实现MongoDB的复杂查询内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Mongodb使用索引进行查询优化的操作方法

    Mongodb使用索引进行查询优化的操作方法

    为集合建立合适的索引,能够有效的减少查询操作时扫描数据的数量 ,从而提高查询效率,简化了mongodb内部查询工作,这篇文章主要介绍了Mongodb使用索引进行查询优化的操作方法,需要的朋友可以参考下
    2024-06-06
  • Mongodb数据库误删后的恢复方法(两种)

    Mongodb数据库误删后的恢复方法(两种)

    本文给大家分享两种方法来实现Mongodb数据库误删后的恢复,每种方法给大家介绍的都非常详细,需要的朋友参考下吧
    2018-08-08
  • MongoDB快速入门笔记(一)之windows下安装MongoDB方法

    MongoDB快速入门笔记(一)之windows下安装MongoDB方法

    MongoDB 是一个基于分布式文件存储的数据库。由 C++ 语言编写。本文重点给大家介绍MongoDB快速入门笔记(一)之windows下安装MongoDB方法,非常不错具有参考借鉴价值,感兴趣的朋友一起看下吧
    2016-06-06
  • MongoDB使用$addToSet向数组中添加元素的操作代码

    MongoDB使用$addToSet向数组中添加元素的操作代码

    使用方法$addToSet, 向数组中添加不存在的元素,如果元素已经存在于目标数组当中,则使用$addToSet不会更新当前文档,本文给大家介绍了MongoDB使用$addToSet向数组中添加元素的操作代码,感兴趣的小伙伴跟着小编一起来看看吧
    2024-06-06
  • MongoDB在不同主机间复制数据库和集合的教程

    MongoDB在不同主机间复制数据库和集合的教程

    MongoDB自带了clone一族JavaScript函数来进行数据的复制,这里我们总结了MongoDB在不同主机间复制数据库和集合的教程,列举出了一些主从复制操作中常用的重要函数:
    2016-07-07
  • Mongodb读数据操作

    Mongodb读数据操作

    今天小编就为大家分享一篇关于Mongodb读数据操作,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2019-01-01
  • MongoDB快速入门笔记(四)之MongoDB查询文档操作实例代码

    MongoDB快速入门笔记(四)之MongoDB查询文档操作实例代码

    MongoDB 是一个基于分布式文件存储的数据库。接下来通过本文给大家介绍MongoDB快速入门笔记(四)之MongoDB查询文档操作实例代码,感兴趣的朋友一起学习吧
    2016-06-06
  • MongoDB的安装及配置文件选项全解

    MongoDB的安装及配置文件选项全解

    本文收录了MongoDB的安装及配置文件选项全解,介绍了MongoDB安装的方法以及环境下的一些重要文件,还有最重要的是详细地罗列了配置文件中的选项含义和参数,需要的朋友可以参考下
    2016-07-07
  • 在MongoDB中实现时间范围查询的代码详解

    在MongoDB中实现时间范围查询的代码详解

    MongoDB作为一个高性能、开源、无模式的文档型数据库,广泛应用于各种需要灵活数据模型的应用场景中,在处理与时间相关的数据时,MongoDB提供了强大的查询能力,本文将详细介绍如何在MongoDB中执行时间范围查询,需要的朋友可以参考下
    2024-08-08
  • 使用centos系统中的crontab命令对mongodb定时备份恢复

    使用centos系统中的crontab命令对mongodb定时备份恢复

    编写centos脚本使用crontab命令对mongodb定时执行备份与恢复操作,并删除指定天数前的备份
    2018-03-03

最新评论