it编程 > 数据库 > mongodb

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

114人参与 2024-12-05 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的复杂查询内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!

(0)
打赏 微信扫一扫 微信扫一扫

您想发表意见!!点此发布评论

推荐阅读

MongoDB配置用户名和密码的操作步骤

12-12

如何通过MongoDB Atlas 实现语义搜索与 RAG(迈向AI的搜索机制)

11-16

批量清理mongodb历史数据的方法详解

01-08

mongodb数据迁移详细步骤(亲测成功!)

01-08

使用Locust对MongoDB进行负载测试的操作步骤

01-09

Windows系统启动MongoDB报错无法连接服务器的问题及解决方案

10-24

猜你喜欢

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论