基于?MongoTemplate實(shí)現(xiàn)MongoDB的復(fù)雜查詢功能
MongoDB是典型的非關(guān)系型數(shù)據(jù)庫,但是它的功能越來越復(fù)雜,很多項(xiàng)目中,我們?yōu)榱丝焖偻卣梗踔林苯邮褂肕ongo 來替代傳統(tǒng)DB做數(shù)據(jù)持久化。
雖然MongoDB在支持具體業(yè)務(wù)時沒有問題,但是由于它是文檔型數(shù)據(jù)庫,擁有一套獨(dú)立的語法,不再支持傳統(tǒng)的SQL。
開發(fā)人員發(fā)現(xiàn)在實(shí)際開發(fā)過程中,由于語法問題,在處理復(fù)雜的業(yè)務(wù)查詢時,不知該如何下手,使不上勁。
在這里我總結(jié)了一下接觸到的使用場景:
如果是簡單的業(yè)務(wù),那么我們直接使用spring JPA來實(shí)現(xiàn)就可以,比如這些操作:
1、創(chuàng)建
2、刪除
3、修改
4、簡單的查詢
因?yàn)檫@些語句的邏輯往往不是很復(fù)雜,JPA完全可以勝任,而且還清晰直觀。
如果是復(fù)雜的場景,我們就使用MongoTemplate 來組織條件邏輯:
假設(shè)背景是有張Student 表,結(jié)構(gòu)如下:
我們已經(jīng)預(yù)先插入了下邊的數(shù)據(jù):
(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)]
觀察代碼,我們發(fā)現(xiàn)需要首先創(chuàng)建一個Query 實(shí)例,表示是一個查詢動作。query 對象,繼續(xù)補(bǔ)充一個Criteria 實(shí)例。Criteria 英[kra?'t??ri?] 譯為比標(biāo)準(zhǔn)、準(zhǔn)則、尺度。我們可以直接理解為查詢條件。注意Criteria 實(shí)例是由 Criteria.where 方法創(chuàng)建出來的。(防盜連接:本文首發(fā)自http://www.cnblogs.com/jilodream/ )這是一個簡單工廠,參數(shù)為要查詢的表的列名(文檔的字段)。再跟一個in() ,表示列的in 操作,in() 中跟的是in操作的值。最后直接用mongoTemplate 實(shí)例執(zhí)行find 操作就好,條件為查詢邏輯和表對應(yīng)的類文件。我們這里使用的是in 操作,除此之外,常用的還有
方法 | 作用 | 類比sql |
gt | 表示 大于 | > |
gte | 表示 大于等于 | >= |
lt | 表示 小于 | < |
lte | 表示 小于等于 | <= |
ne | 表示 不等于 | != |
nin | 表示 不屬于 | not in |
is | 表示等于 | = |
regex | 表示 like (注意后面跟正則表達(dá)式,如 "^.*" + queryKeyWord + ".*$") | like ‘%關(guān)鍵字%’ |
這些都是基本操作,有sql經(jīng)驗(yàn)的同學(xué)肯定明白具體怎么使用。
我們再補(bǔ)充一個模糊查詢的例子:
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)接著來看一個相對復(fù)雜點(diǎn)的組合條件:兩個或條件,類似于SQL中的: A表達(dá)式 OR B表達(dá)式,代碼如下
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); }
執(zhí)行效果如下:
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)]
我們創(chuàng)建好兩個Criteria的簡單條件之后,再創(chuàng)建一個新的Criteria 實(shí)例,用一個or操作將二者關(guān)聯(lián)起來.
query 接收最新的Criteria 實(shí)例,然后執(zhí)行查詢即可。
這里的寫法類似于sql中的
where name like "%ong%" or age != 15
如果是兩個AND 條件,類似于SQL中的: (防盜連接:本文首發(fā)自http://www.cnblogs.com/jilodream/ )A表達(dá)式 AND B表達(dá)式,用法和or的使用方法是一樣的 。這里就不舉例了,
我們這里寫一個復(fù)雜的用法:
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)](防盜連接:本文首發(fā)自http://www.cnblogs.com/jilodream/ )
這里的寫法類似于sql中的
where ( description = "nice" and classNo in (1 ,2 ,3) ) or ("name like %ong%" or age != 15)
總體來看:一個Criteria 實(shí)例,就是一個查詢條件。
我們可以通過 or、and 操作來不斷的組合生成一個新的Criteria實(shí)例,也就是一個新的查詢條件 ,并且可以以此查詢條件繼續(xù)組合生成更高級的Criteria,以此不斷的類推。
這個過程就像壘積木一樣:
(3) 接著我們整合下分頁功能,并且以班級排序
PageRequest pageable = PageRequest.of(pageIndex - 1, pageSize); Query pageQuery=query.with(pageable).with(Sort.by(Sort.Direction.DESC,"classNo"));
注意分頁時,頁碼數(shù)是從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)]
到此這篇關(guān)于基于 MongoTemplate 實(shí)現(xiàn)MongoDB的復(fù)雜查詢的文章就介紹到這了,更多相關(guān)基于 MongoTemplate 實(shí)現(xiàn)MongoDB的復(fù)雜查詢內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
使用centos系統(tǒng)中的crontab命令對mongodb定時備份恢復(fù)
編寫centos腳本使用crontab命令對mongodb定時執(zhí)行備份與恢復(fù)操作,并刪除指定天數(shù)前的備份2018-03-03MongoDB中文學(xué)習(xí)入門教程(包括安裝配置和增刪改查)
本文主要介紹了MongoDB的基本知識和操作,MongoDB是一種面向文檔的無結(jié)構(gòu)化數(shù)據(jù)庫系統(tǒng),具有靈活性、可擴(kuò)展性和高性能等優(yōu)點(diǎn),安裝和配置MongoDB也非常簡單,使用MongoDB的API進(jìn)行操作也非常方便,在實(shí)際使用中,MongoDB可以作為常規(guī)數(shù)據(jù)存儲或NoSQL解決方案的替代品2024-01-01MongoDB系列教程(七):MongoDb數(shù)據(jù)結(jié)構(gòu)詳解
這篇文章主要介紹了MongoDB系列教程(七):MongoDb數(shù)據(jù)結(jié)構(gòu)詳解,本文講解了Collections、Document、GridFS等3種數(shù)據(jù)結(jié)構(gòu),需要的朋友可以參考下2015-05-05在CentOS?7上安裝MongoDB數(shù)據(jù)庫的方法步驟
MongoDB作為一款高性能、開源的NoSQL數(shù)據(jù)庫,因其靈活性和可擴(kuò)展性,成為了眾多開發(fā)者和企業(yè)的首選,這篇文章主要給大家介紹了關(guān)于在CentOS?7上安裝MongoDB數(shù)據(jù)庫的方法步驟,需要的朋友可以參考下2024-09-09SpringBoot+MongoDB實(shí)現(xiàn)物流訂單系統(tǒng)的代碼
這篇文章主要介紹了SpringBoot+MongoDB實(shí)現(xiàn)物流訂單系統(tǒng)的代碼,本文通過圖文實(shí)例相結(jié)合給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-09-09剖析后OpLog訂閱MongoDB的數(shù)據(jù)變更就沒那么難了
這篇文章主要為介紹了OpLog訂閱MongoDB的數(shù)據(jù)變更,希望讀完本文后讓你對OpLog訂閱MongoDB的數(shù)據(jù)變更不在頭疼,有需要的朋友可以借鑒參考下,希望能夠有所幫助2022-02-02