SpringBoot整合MongoDB全過(guò)程
一、環(huán)境準(zhǔn)備
①添加 SpringData 依賴(lài):
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
②配置 yml 文件,官方連接配置文檔
方式一:
spring:
data:
mongodb:
uri: mongodb://root:123456@1.15.76.95:27017/library?authSource=admin
方式二:
spring:
data:
mongodb:
username: root
password: 123456
host: 1.15.76.95
port: 27017
database: library
authentication-database: admin
③直接注入 MongoTemplate 進(jìn)行操作
@Resource MongoTemplate mongoTemplate;
二、集合操作
@Test
public void testCollection(){
boolean exists = mongoTemplate.collectionExists("borrow");
if(exists) {
// 刪除集合
mongoTemplate.dropCollection("borrow");
}else {
// 創(chuàng)建集合
mongoTemplate.createCollection("borrow");
}
Set<String> collectionNames = mongoTemplate.getCollectionNames();
System.out.println(collectionNames.toString()); // [borrow, book, user]
}
三、文檔操作
3.1 實(shí)體類(lèi)
@Document
- 修飾范圍:用在類(lèi)上。
- 作用:用來(lái)映射這個(gè)類(lèi)的一個(gè)對(duì)象為 Mongo 中一條文檔數(shù)據(jù)。
- 屬性:(value 、collection) 用來(lái)指定操作的集合名稱(chēng)。
@MongoId
- 修飾范圍:用在成員變量、方法上。
- 作用:用來(lái)將成員變量的值映射為文檔的 _id 的值。
@Field
- 修飾范圍:用在成員變量、方法上。
- 作用:用來(lái)將成員變量及其值映射為文檔中一個(gè) key:value 對(duì)。
- 屬性:(name , value) 用來(lái)指定在文檔中 key 的名稱(chēng),默認(rèn)為成員變量名。
@Transient
- 修飾范圍:用在成員變量、方法上。
- 作用:用來(lái)指定此成員變量不參與文檔的序列化。
@Data
@AllArgsConstructor
@NoArgsConstructor
@Document("user")
public class User {
@MongoId
private Integer uid;
@Field
private String name;
@Field
private String password;
@Field
private Integer age;
}
3.2 添加文檔
insert 方法返回值是新增的 Document 對(duì)象,里面包含了新增后 id 的值。
如果集合不存在會(huì)自動(dòng)創(chuàng)建集合。
@Test
public void test1() {
// _id存在時(shí)更新數(shù)據(jù)
mongoTemplate.save(new User(1, "aaa", "123456", 20));
// _id存在時(shí)拋出異常
mongoTemplate.insert(new User(2, "bbb", "113456", 21));
List<User> list = Arrays.asList(
new User(3, "ccc", "124266", 22),
new User(4, "ddd", "136521", 23),
new User(5, "eee", "147258", 24));
// 批量插入
mongoTemplate.insert(list, User.class);
}
通過(guò) Spring Data MongoDB 還會(huì)給集合中多加一個(gè) _class 的屬性,存儲(chǔ)新增時(shí) Document 對(duì)應(yīng) Java 中類(lèi)的全限定路徑。
這么做為了查詢(xún)時(shí)能把 Document 轉(zhuǎn)換為 Java 類(lèi)型。

3.3 查詢(xún)文檔
Query類(lèi)作為查詢(xún)條件的容器,用于放置 Criteria 條件接口。Criteria是標(biāo)準(zhǔn)查詢(xún)的接口,可以引用靜態(tài)的Criteria.where()將字段和條件組合在一起進(jìn)行查詢(xún)。
@Test
public void test1() {
System.out.println("==========查詢(xún)所有文檔===========");
List<User> list = mongoTemplate.findAll(User.class);
list.forEach(System.out::println);
System.out.println("==========根據(jù)_id查詢(xún)===========");
User user = mongoTemplate.findById(3, User.class);
System.out.println(user);
System.out.println("==========findOne返回第一個(gè)文檔===========");
User one = mongoTemplate.findOne(new Query(), User.class);
System.out.println(one);
}
@Test
public void test2() {
System.out.println("==========條件查詢(xún)===========");
// 查詢(xún)name為"eee"的用戶(hù)
Query query1 = new Query(Criteria.where("name").is("eee"));
// 查詢(xún) age<23 的用戶(hù)
Query query2 = new Query(Criteria.where("age").lt(23));
// 查詢(xún) 21<=age<24 的用戶(hù)
Query query3 = new Query(Criteria.where("age").gte(21).lt(24));
// 模糊查詢(xún)
Query query4 = new Query(Criteria.where("password").regex("123"));
System.out.println("==========多條件查詢(xún)===========");
// 查詢(xún) age<24 且 密碼包含"123" 的用戶(hù)
Criteria criteria1 = new Criteria();
criteria1.andOperator(Criteria.where("age").lt(24), Criteria.where("password").regex("123"));
Query query5 = new Query(criteria1);
// 查詢(xún) age>23 或 密碼包含"456" 的用戶(hù)
Criteria criteria2 = new Criteria();
criteria2.orOperator(Criteria.where("age").gt(23), Criteria.where("password").regex("456"));
Query query6 = new Query(criteria2);
List<User> list = mongoTemplate.find(query6, User.class);
list.forEach(System.out::println);
}
@Test
public void test3() {
System.out.println("==========排序===========");
Query query1 = new Query();
query1.with(Sort.by(Sort.Order.desc("age")));
System.out.println("==========分頁(yè)===========");
Query query2 = new Query();
query2.skip(0).limit(3);
List<User> list = mongoTemplate.find(query2, User.class);
list.forEach(System.out::println);
}
使用 JSON 字符串方式查詢(xún):
@Test
public void testFindByJson() {
// 等值查詢(xún)
Query query1 = new BasicQuery("{name:'eee'}");
// 多條件查詢(xún)
Query query2 = new BasicQuery("{age:{$lt:24}, password:{$regex:'123'}}");
Query query3 = new BasicQuery("{$or:[{age:{$gt:23}}, {password:{$regex:'456'}}]}");
List<User> list = mongoTemplate.find(query3, User.class);
list.forEach(System.out::println);
}
3.4 修改文檔
在 Mongodb 中無(wú)論是使用客戶(hù)端 API 還是使用 Spring Data,更新返回結(jié)果一定是受行數(shù)影響。如果更新后的結(jié)果和更新前的結(jié)果是相同,返回 0。
updateFirst():只更新滿(mǎn)足條件的第一條記錄。updateMulti():更新所有滿(mǎn)足條件的記錄。upsert():沒(méi)有符合條件的記錄則插入數(shù)據(jù)。
@Test
public void test1() {
Query query = new Query(Criteria.where("name").is("eee"));
Update update = new Update();
update.set("age", 25);
// updateFirst() 只更新滿(mǎn)足條件的第一條記錄
UpdateResult updateResult = mongoTemplate.updateFirst(query, update, User.class);
System.out.println("返回修改的記錄數(shù): " + updateResult.getModifiedCount());
}
@Test
public void test2() {
Query query = new Query(Criteria.where("age").gt(23));
Update update = new Update();
update.inc("age", 1);
// updateMulti() 更新所有滿(mǎn)足條件的記錄
UpdateResult updateResult = mongoTemplate.updateMulti(query, update, User.class);
System.out.println("返回修改的記錄數(shù): " + updateResult.getModifiedCount());
}
@Test
public void test3() {
// query查詢(xún)結(jié)果不存在
Query query = new Query(Criteria.where("name").is("ggg"));
Update update = new Update();
update.set("age", 28);
update.setOnInsert("_id", 7); //不存在時(shí)插入
// upsert() 沒(méi)有符合條件的記錄則插入數(shù)據(jù)
UpdateResult updateResult = mongoTemplate.upsert(query, update, User.class);
System.out.println("返回修改的記錄數(shù): " + updateResult.getModifiedCount());
}
3.5 刪除文檔
@Test
public void testDelete() {
//刪除所有文檔, 不如用dropCollection()
//mongoTemplate.remove(new Query(),Employee.class);
//條件刪除
Query query = new Query(Criteria.where("name").is("fff"));
mongoTemplate.remove(query, User.class);
}
四、聚合操作
4.1 使用 Aggregation 實(shí)現(xiàn)
用 Aggregation 集合接收聚合操作,用 MongoTemplate 對(duì)象直接調(diào)用 aggregate,傳入聚合操作集合、表名、映射對(duì)象。
@Test
public void testAggregation() {
// 1.先定義聚合操作
MatchOperation match = Aggregation.match(Criteria.where("type").is("novel"));
SortOperation sort = Aggregation.sort(Sort.Direction.ASC, "favCount");
// 2.按順序組合每一個(gè)聚合步驟
TypedAggregation<Book2> typedAggregation = Aggregation.newAggregation(Book2.class, match, sort);
// 3.執(zhí)行聚合操作, 可以使用 Document、Map、自定義實(shí)體類(lèi) 接收結(jié)果
AggregationResults<Document> aggregate = mongoTemplate.aggregate(typedAggregation, Document.class);
List<Document> results = aggregate.getMappedResults();
results.forEach(System.out::println);
}
4.2 使用 Aggregates 實(shí)現(xiàn)
用 Aggregates 和 Bson 構(gòu)建聚合操作對(duì)象,用預(yù)先生成的 MongoCollection 對(duì)象調(diào)用 aggregate 執(zhí)行。
@Test
public void testAggregates(){
// 1.先通過(guò)集合名拿到所有文檔
MongoCollection<Document> collection = mongoTemplate.getCollection("book2");
// 2.Aggregates提供各種聚合操作符,返回一個(gè)Bson對(duì)象
Bson matchBson = Aggregates.match(new Document("type", "travel"));
// Bson matchBson = Aggregates.match(Filters.eq("type", "travel"));//Filters來(lái)實(shí)現(xiàn)過(guò)濾
Bson sortBson = Aggregates.sort(Sorts.ascending("favCount"));
// Bson sortBson = Aggregates.sort(new Document("favCount", 1));
// 3.構(gòu)建一個(gè)List<Bson>, 并把每一個(gè)聚合操作按順序加進(jìn)去
List<Bson> bsonList = new ArrayList<>();
bsonList.add(matchBson);
bsonList.add(sortBson);
// 4.最后傳入aggregate方法中執(zhí)行,并且接收結(jié)果集
AggregateIterable<Document> resultList = collection.aggregate(bsonList);
resultList.forEach(System.out::println);
}
示例一:統(tǒng)計(jì)文檔中的書(shū)籍總量、收藏總數(shù)、平均收藏量
@Test
public void test1() {
MongoCollection<Document> collection = mongoTemplate.getCollection("book2");
Bson groupBson = Aggregates.group(null,
Accumulators.sum("bookCount", 1),
Accumulators.sum("favCount", "$favCount"),
Accumulators.avg("favAvg", "$favCount"));
List<Bson> bsonList = new ArrayList<>();
bsonList.add(groupBson);
AggregateIterable<Document> resultList = collection.aggregate(bsonList);
resultList.forEach(System.out::println);
}
示例二:統(tǒng)計(jì)tag標(biāo)簽的熱度排行 (根據(jù)favCount總量排行即為熱度)
@Test
public void test4() {
MongoCollection<Document> collection = mongoTemplate.getCollection("book2");
Bson unwindBson = Aggregates.unwind("$tag");
Bson groupBson = Aggregates.group("$tag", Accumulators.sum("favCount", "$favCount"));
Bson sortBson = Aggregates.sort(new Document("favCount", -1));
List<Bson> bsonList = new ArrayList<>();
bsonList.add(unwindBson);
bsonList.add(groupBson);
bsonList.add(sortBson);
AggregateIterable<Document> resultList = collection.aggregate(bsonList);
resultList.forEach(System.out::println);
}
4.3 應(yīng)用案例
示例一:統(tǒng)計(jì)每個(gè)作者的每本book的收藏?cái)?shù)
@Test
public void test1() {
GroupOperation group = Aggregation
.group("$author.name", "$title")
.sum("$favCount").as("favCount");
TypedAggregation<Book2> typedAggregation = Aggregation.newAggregation(Book2.class, group);
AggregationResults<Document> aggregate = mongoTemplate.aggregate(typedAggregation, Document.class);
List<Document> mappedResults = aggregate.getMappedResults();
mappedResults.forEach(System.out::println);
}
示例二:每個(gè)作者的book的tag合集
@Test
public void test2() {
UnwindOperation unwind = Aggregation.unwind("$tag");
GroupOperation group = Aggregation
.group("$author.name")
.addToSet("$type").as("types");
TypedAggregation<Book2> typedAggregation = Aggregation.newAggregation(Book2.class, unwind, group);
AggregationResults<Document> aggregate = mongoTemplate.aggregate(typedAggregation, Document.class);
List<Document> mappedResults = aggregate.getMappedResults();
mappedResults.forEach(System.out::println);
}
示例三:聯(lián)表查詢(xún)用戶(hù)以及對(duì)應(yīng)的訂單信息
@Test
public void test1() {
LookupOperation lookup = Aggregation.lookup("order", "_id", "customerId", "order");
TypedAggregation<Customer> orderTypedAggregation = Aggregation.newAggregation(Customer.class, lookup);
AggregationResults<Document> aggregate = mongoTemplate.aggregate(orderTypedAggregation, Document.class);
List<Document> mappedResults = aggregate.getMappedResults();
mappedResults.forEach(System.out::println);
}

示例四:聯(lián)表查詢(xún)訂單信息以及對(duì)應(yīng)的商品項(xiàng)
@Test
public void test2() {
LookupOperation lookup = Aggregation.lookup("orderItem", "_id", "orderId", "orderItem");
TypedAggregation<Order> orderItemTypedAggregation = Aggregation.newAggregation(Order.class, lookup);
AggregationResults<Document> aggregate = mongoTemplate.aggregate(orderItemTypedAggregation, Document.class);
List<Document> mappedResults = aggregate.getMappedResults();
mappedResults.forEach(System.out::println);
}

總結(jié)
本文是對(duì)MongoDB的學(xué)習(xí),SpringBoot整合MongoDB的SpringData,配置文件中如何連接,實(shí)體類(lèi)如何映射到文檔,如何通過(guò)API進(jìn)行集合操作和文檔的增刪查改。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Springboot?配置SqlSessionFactory方式
這篇文章主要介紹了Springboot?配置SqlSessionFactory方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-12-12
Java swing實(shí)現(xiàn)音樂(lè)播放器桌面歌詞字體變色效果
這篇文章主要為大家詳細(xì)介紹了Java swing實(shí)現(xiàn)音樂(lè)播放器桌面歌詞字體變色效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-06-06
Mybatis generator自動(dòng)生成代碼插件實(shí)例解析
這篇文章主要介紹了Mybatis generator自動(dòng)生成代碼插件實(shí)例解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-09-09
java靜態(tài)方法里使用spring的注入對(duì)象方式
本文分析了在使用Spring框架時(shí),靜態(tài)方法中引用非靜態(tài)變量導(dǎo)致空指針的問(wèn)題,并提出了使用`@PostConstruct`注解、`@Value`注解、構(gòu)造注入和`InitializingBean`接口等解決方案2026-04-04
java Spring MVC4環(huán)境搭建實(shí)例詳解(步驟)
spring WEB MVC框架提供了一個(gè)MVC(model-view-controller)模型-視圖-控制器的結(jié)構(gòu)和組件,利用它可以開(kāi)發(fā)更靈活、松耦合的web應(yīng)用。MVC模式使得整個(gè)服務(wù)應(yīng)用的各部分(控制邏輯、業(yè)務(wù)邏輯、UI界面展示)分離開(kāi)來(lái),使它們之間的耦合性更低2017-08-08
SpringBoot基于數(shù)據(jù)庫(kù)實(shí)現(xiàn)定時(shí)任務(wù)過(guò)程解析
這篇文章主要介紹了SpringBoot基于數(shù)據(jù)庫(kù)實(shí)現(xiàn)定時(shí)任務(wù)過(guò)程解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-12-12
java實(shí)現(xiàn)RTF文件查看器(附帶源碼)
這篇文章主要介紹了一個(gè)基于?Java?Swing?的?RTF?文件查看器,既可作為輕量級(jí)桌面應(yīng)用,也可嵌入到更大規(guī)模的管理系統(tǒng)中,滿(mǎn)足用戶(hù)對(duì)?RTF?文檔的即時(shí)預(yù)覽、樣式保真和簡(jiǎn)單導(dǎo)航需求2025-06-06
Java?ConcurrentHashMap實(shí)現(xiàn)線(xiàn)程安全的代碼示例
眾所周知ConcurrentHashMap是HashMap的多線(xiàn)程版本,HashMap?在并發(fā)操作時(shí)會(huì)有各種問(wèn)題,而這些問(wèn)題,只要使用ConcurrentHashMap就可以完美解決了,本文將給詳細(xì)介紹ConcurrentHashMap是如何保證線(xiàn)程安全的2023-05-05

