springboot整合mongodb使用詳解
一、mongodb簡(jiǎn)介
1.1 什么是mongodb
MongoDB是一個(gè)文檔數(shù)據(jù)庫(kù)(以 JSON 為數(shù)據(jù)模型),由C++語(yǔ)言編寫,旨在為WEB應(yīng)用提供可擴(kuò)展的高性能數(shù)據(jù)存儲(chǔ)解決方案。
1.2 mongodb特點(diǎn)
- MongoDB是一個(gè)介于關(guān)系數(shù)據(jù)庫(kù)和非關(guān)系數(shù)據(jù)庫(kù)之間的產(chǎn)品,是非關(guān)系數(shù)據(jù)庫(kù)當(dāng)中功能最豐富,最像關(guān)系數(shù)據(jù)庫(kù)的;
- 它支持的數(shù)據(jù)結(jié)構(gòu)非常松散,數(shù)據(jù)格式為BSON,一種類似JSON的二進(jìn)制形式的存儲(chǔ)格
- 式,簡(jiǎn)稱Binary JSON ,和JSON一樣支持內(nèi)嵌的文檔對(duì)象和數(shù)組對(duì)象,因此可以存儲(chǔ)比較復(fù)雜的數(shù)據(jù)類型;
- MongoDB最大特點(diǎn)是支持的查詢語(yǔ)言非常強(qiáng)大,語(yǔ)法有點(diǎn)類似于面向?qū)ο蟮牟樵冋Z(yǔ)言,幾乎可以實(shí)現(xiàn)類似關(guān)系數(shù)據(jù)庫(kù)單表查詢的絕大部分功能,而且還支持對(duì)數(shù)據(jù)建立索引;
- 原則上 Oracle 和MySQL 能做的事情,MongoDB 都能做(包括 ACID 事務(wù));
二、mongodb中的核心術(shù)語(yǔ)
在正式學(xué)習(xí)mogodb之前,有必要對(duì)mogodb中的基本術(shù)語(yǔ)和相關(guān)的語(yǔ)法做一個(gè)簡(jiǎn)單了解,就像學(xué)習(xí)mysql必須掌握其基本語(yǔ)法、DDL、DML等一樣的道理,當(dāng)然學(xué)習(xí)mogodb時(shí)可以類比mysql中的數(shù)據(jù)庫(kù),表和字段進(jìn)行理解。
2.1 mogodb與數(shù)據(jù)庫(kù)對(duì)比
MongoDB 概念與關(guān)系型數(shù)據(jù)庫(kù)( RDBMS )非常類似,見(jiàn)下表;

2.2 mongodb中的核心概念
關(guān)于上述表中關(guān)于mongodb各個(gè)術(shù)語(yǔ),再做簡(jiǎn)單的補(bǔ)充說(shuō)明:
數(shù)據(jù)庫(kù)(database)
最外層的概念,可以理解為邏輯上的名稱空間,一個(gè)數(shù)據(jù)庫(kù)包含多個(gè)不同名稱的集合
集合(collection)
相當(dāng)于SQL中的表,一個(gè)集合可以存放多個(gè)不同的文檔
文檔(document)
一個(gè)文檔相當(dāng)于數(shù)據(jù)表中的一行,由多個(gè)不同的字段組成
字段(field)
文檔中的一個(gè)屬性,等同于列(column)
索引(index)
獨(dú)立的檢索式數(shù)據(jù)結(jié)構(gòu),與SQL概念一致
id
每個(gè)文檔中都擁有一個(gè)唯一的id字段,相當(dāng)于SQL中的主鍵(primary key)
視圖(view)
可以看作一種虛擬的(非真實(shí)存在的)集合,與SQL中的視圖類似。從MongoDB3.4版本開始提供了視圖功能,其通過(guò)聚合管道技術(shù)實(shí)現(xiàn)
聚合操作($lookup)
MongoDB用于實(shí)現(xiàn)“類似”表連接(tablejoin)的聚合操作符
2.3 與關(guān)系數(shù)據(jù)庫(kù)的差異
盡管這些概念大多與SQL標(biāo)準(zhǔn)定義類似,但MongoDB與傳統(tǒng)RDBMS仍然存在不少差異,包括:
2.3.1 半結(jié)構(gòu)化
半結(jié)構(gòu)化,在一個(gè)集合中,文檔所擁有的字段并不需要是相同的,而且也不需要對(duì)所用的字段進(jìn)行聲明,因此,MongoDB具有很明顯的半結(jié)構(gòu)化特點(diǎn)。
2.3.2 支持多級(jí)嵌套
除了松散的表結(jié)構(gòu),文檔還可以支持多級(jí)的嵌套、數(shù)組等靈活的數(shù)據(jù)類型,非常契合面向?qū)ο蟮木幊棠P汀?/p>
2.3.3 關(guān)系弱化
弱關(guān)系,MongoDB沒(méi)有外鍵的約束,也沒(méi)有非常強(qiáng)大的表連接能力。類似的功能需要使用聚合管道技術(shù)來(lái)彌補(bǔ)。
三、mongodb 技術(shù)優(yōu)勢(shì)和應(yīng)用場(chǎng)景
3.1 mongodb 技術(shù)優(yōu)勢(shì)
傳統(tǒng)的關(guān)系型數(shù)據(jù)庫(kù)(如MySQL),在數(shù)據(jù)操作的“三高”需求以及應(yīng)對(duì)Web2.0的網(wǎng)站需求面前,逐漸開始顯得吃力,對(duì)于數(shù)據(jù)庫(kù)來(lái)說(shuō),盡管可以通過(guò)集群或其他方式對(duì)單節(jié)點(diǎn)的mysql實(shí)例進(jìn)行擴(kuò)展,但這樣帶來(lái)的成本和代價(jià)也是巨大的,由于mongodb從一開始就是為分布式而生,面對(duì)海量數(shù)據(jù),高并發(fā)的場(chǎng)景有得天獨(dú)厚的優(yōu)勢(shì),同時(shí)其豐富的集群模式可以適應(yīng)企業(yè)不同的數(shù)據(jù)運(yùn)維和部署場(chǎng)景。
關(guān)于三高的解釋補(bǔ)充
1、High performance - 對(duì)數(shù)據(jù)庫(kù)高并發(fā)讀寫的需求;
2、Huge Storage - 對(duì)海量數(shù)據(jù)的高效率存儲(chǔ)和訪問(wèn)的需求;
3、High Scalability && High Availability- 對(duì)數(shù)據(jù)庫(kù)的高可擴(kuò)展性和高可用性的需求;
3.2 mongodb 應(yīng)用場(chǎng)景
從目前阿里云 MongoDB 云數(shù)據(jù)庫(kù)上的用戶看,MongoDB 的應(yīng)用已經(jīng)滲透到各個(gè)領(lǐng)域,這里總結(jié)如下:
游戲場(chǎng)景
使用 MongoDB 存儲(chǔ)游戲用戶信息,用戶的裝備、積分等直接以內(nèi)嵌文檔的形式存儲(chǔ),方便查詢、更新;
物流場(chǎng)景
使用 MongoDB 存儲(chǔ)訂單信息,訂單狀態(tài)在運(yùn)送過(guò)程中會(huì)不斷更新,以MongoDB 內(nèi)嵌
數(shù)組的形式來(lái)存儲(chǔ),一次查詢就能將訂單所有的變更讀取出來(lái);
社交場(chǎng)景
使用 MongoDB 存儲(chǔ)存儲(chǔ)用戶信息,以及用戶發(fā)表的朋友圈信息,通過(guò)地理位置索引實(shí)
現(xiàn)附近的人、地點(diǎn)等功能;
物聯(lián)網(wǎng)場(chǎng)景
使用 MongoDB 存儲(chǔ)所有接入的智能設(shè)備信息,以及設(shè)備匯報(bào)的日志信息,并對(duì)這些信息進(jìn)行多維度的分析;
大數(shù)據(jù)應(yīng)用
使用云數(shù)據(jù)庫(kù)MongoDB作為大數(shù)據(jù)的云存儲(chǔ)系統(tǒng),隨時(shí)進(jìn)行數(shù)據(jù)提取分析,掌握行業(yè)動(dòng)態(tài)
3.3 什么時(shí)候選擇 mongodb
在上述的應(yīng)用場(chǎng)景中,數(shù)據(jù)操作方面有如下一些共同的特點(diǎn):
1)數(shù)據(jù)量大;
2)寫入操作頻繁(讀寫可能都很頻繁);
3)價(jià)值較低的數(shù)據(jù),對(duì)事務(wù)性要求不高;
對(duì)于這樣的數(shù)據(jù),我們更適合使用MongoDB來(lái)實(shí)現(xiàn)數(shù)據(jù)的存儲(chǔ)。在實(shí)際架構(gòu)選型上,除了上述的三個(gè)特點(diǎn)外,如果你還猶豫是否要選擇它?可以考慮以下的一些問(wèn)題:
1、應(yīng)用不需要事務(wù)及復(fù)雜 join 支持;
2、新應(yīng)用,需求會(huì)變,數(shù)據(jù)模型無(wú)法確定,想快速迭代開發(fā);
3、應(yīng)用需要2000-3000以上的讀寫QPS(更高也可以);
4、應(yīng)用需要TB甚至 PB 級(jí)別數(shù)據(jù)存儲(chǔ);
5、應(yīng)用發(fā)展迅速,需要能快速水平擴(kuò)展;
6、應(yīng)用要求存儲(chǔ)的數(shù)據(jù)不丟失;
7、應(yīng)用需要99.999%高可用;
8、應(yīng)用需要大量的地理位置查詢、文本查詢;
如果上述有1個(gè)符合,可以考慮 MongoDB,2個(gè)及以上的符合,選擇 MongoDB肯定不會(huì)錯(cuò)。
四、快速部署 mongodb
為方便后面代碼整合使用,下面通過(guò)docker快速部署起一個(gè)mongodb的服務(wù),按照下面的操作步驟執(zhí)行;
4.1 搭建過(guò)程
4.1.1 拉取鏡像
docker pull mongo:4.4

4.1.2 啟動(dòng)鏡像
在啟動(dòng)鏡像之前先創(chuàng)建一個(gè)數(shù)據(jù)目錄的映射
mkdir data
使用下面的命令啟動(dòng)鏡像
docker run -itd --name mongo -v /usr/local/mongo/data:/data/db -p 27017:27017 mongo:4.4 --auth
參數(shù)說(shuō)明:
1)-p 27017:27017,映射容器服務(wù)的 27017 端口到宿主機(jī)的 27017 端口,外部可以直接通過(guò) 宿主機(jī) ip:27017 訪問(wèn)到 mongo 的服務(wù);
2)--auth:需要密碼才能訪問(wèn)容器服務(wù);

4.2 創(chuàng)建賬戶
4.2.1 登錄mongo容器,并進(jìn)入到【admin】數(shù)據(jù)庫(kù)
docker exec -it mongo mongo admin

4.2.2 創(chuàng)建一個(gè)用戶
mongo 默認(rèn)是沒(méi)有用戶的,這里root只是自己指定的用戶名,可以自己命名
db.createUser({ user:'root',pwd:'123456',roles:[ { role:'userAdminAnyDatabase', db: 'admin'},'readWriteAnyDatabase']});

參數(shù)說(shuō)明:
- 【user:‘root’ 】:設(shè)置用戶名為root;
- 【pwd:‘123456’】:設(shè)置密碼為123456;
- 【role:‘userAdminAnyDatabase’】:只在admin數(shù)據(jù)庫(kù)中可用,賦予用戶所有數(shù)據(jù)庫(kù)的userAdmin權(quán)限;
- 【db: ‘admin’】:可操作的數(shù)據(jù)庫(kù);
- 【‘readWriteAnyDatabase’】:賦予用戶讀寫權(quán)限;
dbAdmin:允許用戶在指定數(shù)據(jù)庫(kù)中執(zhí)行管理函數(shù),如索引創(chuàng)建、刪除,查看統(tǒng)計(jì)或訪問(wèn)system.profile
4.3 連接與測(cè)試
4.3.1連接mongo數(shù)據(jù)庫(kù)
db.auth('root', '123456');

4.3.2 插入與查詢數(shù)據(jù)
db.user.insert({"name":"zhangsan","age":18});
db.user.find();

4.3.3 使用客戶端連接
使用客戶端工具連接,如下圖所示,在下面填寫自己的連接信息即可;

五、整合springboot使用
5.1 前置說(shuō)明
springboot與mongodb整合使用通常有兩種方式,這兩種方式在開發(fā)過(guò)程中結(jié)合實(shí)際需要都可以選擇;
5.1.1 jpa方式整合
使用過(guò)spingboot的jpa操作mysql的同學(xué)應(yīng)該不陌生,這種方式的好處很明顯,就是jpa中針對(duì)常用的對(duì)于數(shù)據(jù)庫(kù)的CRUD操作相關(guān)的API做了封裝,開發(fā)者對(duì)于常用的增刪改查功能開發(fā)起來(lái)效率很高,缺點(diǎn)是如果業(yè)務(wù)操作比較復(fù)雜,需要編寫比較復(fù)雜的sql語(yǔ)句時(shí),使用jpa就不太方便了,盡管jpa也可以通過(guò)注解編寫部分類sql語(yǔ)句,但是語(yǔ)法還是有一定上手成本的。
5.1.2 MongoTemplate 方式整合
很多第三方組件都與springboot做了整合集成,比如像redis提供了redisTemplate,kafka集成springboot時(shí)提供了kafkaTemplate等類似,mongodb也提供了MongoTemplate ,MongoTemplate 提供了滿足日常開發(fā)需要的豐富的API,基本上涵蓋了大部分的場(chǎng)景需求,學(xué)習(xí)成本較低,網(wǎng)上可以參閱的資料也比較豐富??梢宰鳛榈谝贿x擇。
為了更好的滿足日常開發(fā)中的需要,下面將這兩種方式的使用做一個(gè)詳細(xì)的介紹。
5.2 準(zhǔn)備一個(gè)數(shù)據(jù)庫(kù)
為了方便后文中代碼的測(cè)試,基于上面已經(jīng)搭建完成的mongodb服務(wù),使用root賬戶登錄進(jìn)去之后,創(chuàng)建一個(gè)名為 book的collection集合,創(chuàng)建也比較簡(jiǎn)單,使用上面的root用戶登錄進(jìn)客戶端之后,直接輸入下面的命令即可創(chuàng)建;
use 你的數(shù)據(jù)庫(kù)名稱
5.3 jpa方式整合使用
5.3.1 創(chuàng)建一個(gè)springboot的工程
創(chuàng)建一個(gè)空的springboot工程,目錄結(jié)構(gòu)如下:

5.3.2 導(dǎo)入核心依賴
為了接口測(cè)試方便,引入了swagger的相關(guān)依賴;
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
<!--swagger API獲取-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<!--swagger-ui API獲取-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
</dependencies>5.3.3 application 配置文件
application.yml中添加如下配置
spring:
data:
mongodb:
uri: mongodb://root:123456@IP地址:27017/book?authSource=admin&authMechanism=SCRAM-SHA-1
server:
port: 80825.3.4 實(shí)體數(shù)據(jù)對(duì)象
創(chuàng)建一個(gè)Book類,作為與mongo中的book這個(gè)collection集合的映射,對(duì)象中的屬于對(duì)應(yīng)著數(shù)據(jù)庫(kù)中的collection的各個(gè)字段;
@Document(collection="book")
@Data
@AllArgsConstructor
@NoArgsConstructor
public class BookInfo {
@Id
private String id;
@Field("name")
private String name;
@Field("price")
private Integer price;
@Field("publish_time")
private String publishTime;
@Field("comment")
private String comment;
}5.3.5 jpa數(shù)據(jù)持久層
添加一個(gè)與mongodb集合交互的jpa接口,繼承MongoRepository接口,使用過(guò)jpa的同學(xué)對(duì)此應(yīng)該不陌生;
public interface BookRepository extends MongoRepository<BookInfo,String> {
}5.3.6 核心操作接口
為方便測(cè)試,創(chuàng)建一個(gè)接口類,由于基本的增刪改查邏輯相對(duì)比較簡(jiǎn)單,直接調(diào)用MongoRepository即可,下面貼出基本的增刪改查接口
@Autowired
private BookService bookService;
@PostMapping("/save")
public String save(BookInfo bookInfo) {
return bookService.saveBook(bookInfo);
}
@PostMapping("/update")
public String update(BookInfo bookInfo) {
return bookService.update(bookInfo);
}
@GetMapping("/delete")
public String deleteById(String id) {
return bookService.deleteById(id);
}
@PostMapping("/detail")
public BookInfo findById(String id) {
return bookService.findById(id);
}業(yè)務(wù)實(shí)現(xiàn)
@Autowired
private BookRepository bookRepository;
/**
* 保存
* @param bookInfo
* @return
*/
public String saveBook(BookInfo bookInfo){
bookInfo.setId(IdUtil.generateId());
bookRepository.save(bookInfo);
return "save book info success";
}
/**
* 修改
* @param bookInfo
* @return
*/
public String update(BookInfo bookInfo) {
if(StringUtils.isEmpty(bookInfo.getId())){
throw new RuntimeException("ID不能為空");
}
bookRepository.save(bookInfo);
return "save book info success";
}
/**
* 根據(jù)ID刪除
* @param id
* @return
*/
public String deleteById(String id) {
bookRepository.deleteById(id);
return "delete success";
}
/**
* 查詢所有
* @return
*/
public List<BookInfo> findList() {
return bookRepository.findAll();
}
/**
* 根據(jù)ID獲取
* @param id
* @return
*/
public BookInfo findById(String id) {
Optional<BookInfo> bookInfoOptional = bookRepository.findById(id);
return bookInfoOptional.isPresent() ? bookInfoOptional.get() : null;
}以查詢?cè)斍榻涌跒槔趕wagger中做一下測(cè)試,效果如下:

5.3.7 常用復(fù)雜查詢接口
相信很多項(xiàng)目使用mongodb的一個(gè)重要的原因就是使用mongo進(jìn)行查詢時(shí)性能很高,尤其是針對(duì)一些復(fù)雜的查詢場(chǎng)景時(shí)優(yōu)勢(shì)很明顯,下面結(jié)合開發(fā)中其他比較常用的幾個(gè)查詢場(chǎng)景做一下補(bǔ)充;
模糊查詢
主要用到了ExampleMatcher這個(gè)匹配對(duì)象,類似于mysql的: like '%關(guān)鍵字%';
/**
* 模糊查詢
* @param name
* @return
*/
public List<BookInfo> query(String name) {
//構(gòu)建匹配器對(duì)象
ExampleMatcher matcher = ExampleMatcher.matching()
.withStringMatcher(ExampleMatcher.StringMatcher.CONTAINING) //設(shè)置默認(rèn)字符串匹配方式:模糊查詢
.withIgnoreCase(true); //設(shè)置默認(rèn)大小寫忽略方式:true為忽略大小寫
BookInfo bookInfo = new BookInfo();
bookInfo.setName(name);
Example<BookInfo> bookInfoExampleExample = Example.of(bookInfo,matcher);
List<BookInfo> bookInfos = bookRepository.findAll(bookInfoExampleExample);
return bookInfos;
}分頁(yè)查詢
public Page<BookInfo> pageQuery(Integer pageNo,Integer pageSize,String name) {
//構(gòu)造排序器,設(shè)置排序字段
Sort sort = Sort.by(Sort.Direction.ASC,"price");
Pageable pageable = null;
if(Objects.isNull(pageNo) || Objects.isNull(pageSize)){
pageNo = 0;
pageSize=10;
}
pageable = PageRequest.of(pageNo, pageSize, sort);
//創(chuàng)建匹配器,設(shè)置查詢條件
ExampleMatcher matcher = ExampleMatcher.matching() //構(gòu)建匹配器對(duì)象
.withStringMatcher(ExampleMatcher.StringMatcher.CONTAINING) //設(shè)置默認(rèn)字符串匹配方式:模糊查詢
.withIgnoreCase(true); //設(shè)置默認(rèn)大小寫忽略方式:true為忽略大小寫
//設(shè)置查詢條件
BookInfo bookInfo = new BookInfo();
bookInfo.setName(name);
Example<BookInfo> bookExample = Example.of(bookInfo,matcher);
//查詢
Page<BookInfo> page = bookRepository.findAll(bookExample, pageable);
return page;
}sql方式查詢
某些情況下可能已有的API并不能很好的滿足,就需要通過(guò)編寫sql的方式實(shí)現(xiàn)了,在使用jpa操作mysql的時(shí)候俗稱hql語(yǔ)言,關(guān)于使用MongoRepository編寫類sql的相信資料可以參閱相關(guān)資料,網(wǎng)上可以搜到很多,其核心語(yǔ)法仍然是mongodb自身的那些操作語(yǔ)句,只是需要遵照J(rèn)ava中的編寫規(guī)范;
下面提供了幾個(gè)常用的查詢,提供參考
public interface BookRepository extends MongoRepository<BookInfo,String> {
//根據(jù)名稱查詢
@Query("{name: ?0}")
List<BookInfo> findByBookName(String name);
//查詢價(jià)格大于某個(gè)數(shù)的集合
@Query(value = "{price: { $gt: ?0 }}")
List<BookInfo> findByBookPriceThan(int price);
//查詢ID在某個(gè)集合中,類似mysql 的 in ()語(yǔ)法
@Query(value = "{'_id':{$in:?0}}")
List<BookInfo> findAllByIdIn(List<String> ids);
}5.4 MongoTemplate 方式整合使用
MongoTemplate相對(duì)于MongoRepository來(lái)說(shuō),從API的使用上來(lái)說(shuō),選擇更豐富,編碼也更友好,同時(shí)API的使用也更加符合編碼的習(xí)慣,下面再使用MongoTemplate 的方式做一下操作演示
配置文件等信息暫時(shí)不用修改
5.4.1 核心增刪接口
接口層
@RestController
@RequestMapping("/template")
public class BookTemplateController {
@Autowired
private BookTemplateService bookTemplateService;
@PostMapping("/save")
public BookInfo save(BookInfo bookInfo){
return bookTemplateService.save(bookInfo);
}
@PostMapping("/update")
public BookInfo update(BookInfo bookInfo){
return bookTemplateService.update(bookInfo);
}
@GetMapping("/delete")
public String delete(String id){
return bookTemplateService.delete(id);
}
@GetMapping("/details")
public BookInfo details(String id){
return bookTemplateService.findById(id);
}
}業(yè)務(wù)實(shí)現(xiàn)
@Service
public class BookTemplateService {
@Autowired
private MongoTemplate mongoTemplate;
public BookInfo save(BookInfo bookInfo) {
bookInfo.setId(IdUtil.generateId());
BookInfo book = mongoTemplate.save(bookInfo);
return book;
}
public BookInfo update(BookInfo bookInfo) {
if(StringUtils.isEmpty(bookInfo.getId())){
throw new RuntimeException("ID為空");
}
Query query = Query.query(Criteria.where("_id").is(bookInfo.getId()));
BookInfo dbBook = mongoTemplate.findOne(query, BookInfo.class);
if(Objects.isNull(dbBook)){
return null;
}
Update update = new Update();
if(!StringUtils.isEmpty(bookInfo.getName())){
update.set("name",bookInfo.getName());
}
if(!StringUtils.isEmpty(bookInfo.getComment())){
update.set("comment",bookInfo.getComment());
}
if(Objects.nonNull(bookInfo.getPrice())){
update.set("price",bookInfo.getPrice());
}
mongoTemplate.updateFirst(query,update,BookInfo.class);
return bookInfo;
}
public String delete(String id) {
Query query = new Query(Criteria.where("_id").is(id));
mongoTemplate.remove(query,BookInfo.class);
return "deleted";
}
public BookInfo findById(String id) {
BookInfo bookInfo = mongoTemplate.findById(id, BookInfo.class);
return bookInfo;
}
}5.4.2 復(fù)雜查詢接口
在實(shí)際業(yè)務(wù)開發(fā)中,更多的情況下會(huì)用到mongodb較復(fù)雜的查詢,下面列舉一些常用的復(fù)雜查詢的場(chǎng)景提供參考
json字符串方式查詢
如果在API調(diào)用過(guò)程中覺(jué)得書寫不習(xí)慣的話,也支持原生的json語(yǔ)句查詢,即將在客戶端命令行中的查詢語(yǔ)句轉(zhuǎn)為json作為一個(gè)完整的語(yǔ)句進(jìn)行查詢
public List<BookInfo> queryByJson(String name,String type,Integer price) {
//String json1 = "{name:'" + name +"'}";
String json2 = "{$or:[{price:{$gt: '" +price+"'}},{type: '"+type+"'}]}";
Query query = new BasicQuery(json2);
//查詢結(jié)果
List<BookInfo> employees = mongoTemplate.find(query, BookInfo.class);
return employees;
}模糊查詢
類似于mysql中的like
//模糊查詢
public List<BookInfo> queryLike(String key){
Query query = new Query(Criteria.where("name").regex(key));
List<BookInfo> bookInfos = mongoTemplate.find(query, BookInfo.class);
return bookInfos;
}范圍查詢
//查詢價(jià)格大于某個(gè)值
public List<BookInfo> queryMoreThan(Integer price){
Query query = new Query(Criteria.where("price").gte(price));
List<BookInfo> bookInfos = mongoTemplate.find(query, BookInfo.class);
return bookInfos;
}多條件查詢
類似于mysql中的多個(gè)條件通過(guò)and的查詢
//多條件查詢
public List<BookInfo> queryMultiParams(String name,String type,Integer price){
//or 條件查詢
Criteria criteria = new Criteria();
/*criteria.orOperator(
Criteria.where("name").regex(name),
Criteria.where("price").gte(price),
Criteria.where("type").is(type)
);*/
//and 條件查詢
criteria.andOperator(
Criteria.where("price").gte(price),
Criteria.where("type").is(type)
);
Query query = new Query(criteria);
List<BookInfo> bookInfos = mongoTemplate.find(query, BookInfo.class);
return bookInfos;
}
分頁(yè)查詢
//分頁(yè)查詢
public PageInfo<BookInfo> pageQuery(Integer pageIndex,Integer pageSize,String type){
Criteria criteria = new Criteria();
if(!StringUtils.isEmpty(type)){
criteria = Criteria.where("price").gte(type);
}
//TODO 如果有更多的查詢條件,繼續(xù)拼接 ...
Query query = new Query(criteria);
if(Objects.isNull(pageIndex) || Objects.isNull(pageSize)){
pageIndex = 1;
pageSize = 2;
}
//查詢總數(shù)
long total = mongoTemplate.count(query, BookInfo.class);
System.out.println(total);
//查詢結(jié)果根據(jù)價(jià)格排個(gè)序
query.with(Sort.by(Sort.Order.desc("price")))
.skip((pageIndex-1) * pageSize) //指定跳過(guò)記錄數(shù)
.limit(pageSize); //每頁(yè)顯示記錄數(shù)
List<BookInfo> bookInfos = mongoTemplate.find(query, BookInfo.class);
PageInfo<BookInfo> pageInfo = new PageInfo(pageIndex,pageSize,total,bookInfos);
return pageInfo;
}
5.4.3 聚合查詢
聚合操作處理數(shù)據(jù)記錄并返回計(jì)算結(jié)果(諸如統(tǒng)計(jì)平均值,求和等)。聚合操作組值來(lái)自多個(gè)文檔,可以對(duì)分組數(shù)據(jù)執(zhí)行各種操作以返回單個(gè)結(jié)果。聚合操作包含三類:?jiǎn)我蛔饔镁酆稀⒕酆瞎艿?、MapReduce。
單一作用聚合
提供了對(duì)常見(jiàn)聚合過(guò)程的簡(jiǎn)單訪問(wèn),操作都從單個(gè)集合聚合文檔;
聚合管道
聚合管道是一個(gè)數(shù)據(jù)聚合的框架,模型基于數(shù)據(jù)處理流水線的概念。文檔進(jìn)入多級(jí)管道,將文檔轉(zhuǎn)換為聚合結(jié)果;
MapReduce
MapReduce操作具有兩個(gè)階段:處理每個(gè)文檔并向每個(gè)輸入文檔發(fā)射一個(gè)或多個(gè)對(duì)象的map階段,以及reduce組合map操作的輸出階段。
5.4.4 聚合統(tǒng)計(jì)查詢案例
關(guān)于分組聚合統(tǒng)計(jì)的內(nèi)容比較多,限于篇幅這里不做展開,我們將book這個(gè)collection集合的字段進(jìn)行擴(kuò)展(為了進(jìn)行分組聚合使用),并插入一些數(shù)據(jù),如下所示

下面我們要實(shí)現(xiàn)的需求是,
按照book的type字段進(jìn)行分組,
1)統(tǒng)計(jì)每個(gè)type類型下的book的閱讀總數(shù),平均閱讀數(shù);
2)統(tǒng)計(jì)每個(gè)type類型下的book的喜歡總數(shù),平均喜歡的數(shù)量;
完整的代碼如下
public void groupQuery(){
// 查詢條件
Criteria criteria = new Criteria();
MatchOperation matchOperation = Aggregation.match(criteria);
// 查詢包括的字段
ProjectionOperation projectionOperation = Aggregation.project("id", "name","price", "type","readCount","likeCount");
// 分組統(tǒng)計(jì)
GroupOperation groupOperation = Aggregation.group("type")
//.first("type").as("type")
.count().as("typeCount")
.sum("likeCount").as("totalLike")
.avg("likeCount").as("avgLikeCount")
.sum("readCount").as("totalReadCount")
.sum("readCount").as("avgReadCount");
AggregationResults<Map> totalAuthorResult = mongoTemplate.aggregate(Aggregation.newAggregation(BookInfo.class,
matchOperation, projectionOperation, groupOperation), Map.class);
//獲取分類總數(shù)
int typeCount = (int) totalAuthorResult.getMappedResults().size();
System.out.println(typeCount);
//得到最終分組聚合的結(jié)果
List<Map> mappedResults = totalAuthorResult.getMappedResults();
for(Map map :mappedResults){
System.out.println(map.keySet());
}
}通過(guò)debug,可以看到查詢得到的結(jié)果如下

如果你需要獲取最終的各個(gè)分組的統(tǒng)計(jì)結(jié)果,只需遍歷上述的結(jié)果集即可。
六、結(jié)語(yǔ)
關(guān)于mongodb的技術(shù)體系是比較龐大的,本文只是冰山一角,要深入學(xué)習(xí)和掌握mongodb還需要實(shí)際開發(fā)過(guò)程中通過(guò)經(jīng)驗(yàn)的積累才能加深對(duì)mongodb的理解和運(yùn)用,隨著技術(shù)的發(fā)展,mongodb在越來(lái)越多的領(lǐng)域都有著不錯(cuò)的運(yùn)用,因此感興趣的同學(xué)可以在此基礎(chǔ)上深入研究。
以上就是springboot整合mongodb使用詳解的詳細(xì)內(nèi)容,更多關(guān)于springboot整合mongodb的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
SpringBoot http post請(qǐng)求數(shù)據(jù)大小設(shè)置操作
這篇文章主要介紹了SpringBoot http post請(qǐng)求數(shù)據(jù)大小設(shè)置操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-09-09
Java中String、StringBuffer和StringBuilder的區(qū)別
這篇文章主要介紹了Java中String、StringBuffer和StringBuilder的區(qū)別,StringBuilder與StringBuffer都繼承自AbstractStringBuilder類,在AbstractStringBuilder中也是使用字符數(shù)組保存字符串char[]value但是沒(méi)有final關(guān)鍵字修飾,所以這兩個(gè)可變,需要的朋友可以參考下2024-01-01
郵件收發(fā)原理你了解嗎? 郵件發(fā)送基本過(guò)程與概念詳解(一)
你真的了解郵件收發(fā)原理嗎?這篇文章主要為大家詳細(xì)介紹了郵件發(fā)送基本過(guò)程與概念,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-10-10
jar命令修改jar包中的application.yml配置文件
本文主要介紹了jar命令修改jar包中的application.yml配置文件,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-08-08
java nio中的ByteBuffer擴(kuò)展問(wèn)題
這篇文章主要介紹了java nio中的ByteBuffer擴(kuò)展問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-08-08
Spring事件監(jiān)聽(tīng)機(jī)制ApplicationEvent方式
這篇文章主要介紹了Spring事件監(jiān)聽(tīng)機(jī)制ApplicationEvent方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-09-09
java項(xiàng)目新建遇到的兩個(gè)問(wèn)題解決
創(chuàng)建一個(gè)新的Java項(xiàng)目可以通過(guò)多種方式進(jìn)行,包括使用集成開發(fā)環(huán)境(IDE)或手動(dòng)創(chuàng)建,下面這篇文章主要給大家介紹了關(guān)于java項(xiàng)目新建遇到的兩個(gè)問(wèn)題,需要的朋友可以參考下2024-06-06

