SpringBoot整合MongoDB全過程
一、環(huán)境準(zhǔn)備
①添加 SpringData 依賴:
<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í)體類
@Document
- 修飾范圍:用在類上。
- 作用:用來映射這個(gè)類的一個(gè)對象為 Mongo 中一條文檔數(shù)據(jù)。
- 屬性:(value 、collection) 用來指定操作的集合名稱。
@MongoId
- 修飾范圍:用在成員變量、方法上。
- 作用:用來將成員變量的值映射為文檔的 _id 的值。
@Field
- 修飾范圍:用在成員變量、方法上。
- 作用:用來將成員變量及其值映射為文檔中一個(gè) key:value 對。
- 屬性:(name , value) 用來指定在文檔中 key 的名稱,默認(rèn)為成員變量名。
@Transient
- 修飾范圍:用在成員變量、方法上。
- 作用:用來指定此成員變量不參與文檔的序列化。
@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 對象,里面包含了新增后 id 的值。
如果集合不存在會自動創(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); }
通過 Spring Data MongoDB 還會給集合中多加一個(gè) _class
的屬性,存儲新增時(shí) Document 對應(yīng) Java 中類的全限定路徑。
這么做為了查詢時(shí)能把 Document 轉(zhuǎn)換為 Java 類型。
3.3 查詢文檔
Query
類作為查詢條件的容器,用于放置 Criteria 條件接口。Criteria
是標(biāo)準(zhǔn)查詢的接口,可以引用靜態(tài)的Criteria.where()
將字段和條件組合在一起進(jìn)行查詢。
@Test public void test1() { System.out.println("==========查詢所有文檔==========="); List<User> list = mongoTemplate.findAll(User.class); list.forEach(System.out::println); System.out.println("==========根據(jù)_id查詢==========="); 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("==========條件查詢==========="); // 查詢name為"eee"的用戶 Query query1 = new Query(Criteria.where("name").is("eee")); // 查詢 age<23 的用戶 Query query2 = new Query(Criteria.where("age").lt(23)); // 查詢 21<=age<24 的用戶 Query query3 = new Query(Criteria.where("age").gte(21).lt(24)); // 模糊查詢 Query query4 = new Query(Criteria.where("password").regex("123")); System.out.println("==========多條件查詢==========="); // 查詢 age<24 且 密碼包含"123" 的用戶 Criteria criteria1 = new Criteria(); criteria1.andOperator(Criteria.where("age").lt(24), Criteria.where("password").regex("123")); Query query5 = new Query(criteria1); // 查詢 age>23 或 密碼包含"456" 的用戶 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("==========分頁==========="); Query query2 = new Query(); query2.skip(0).limit(3); List<User> list = mongoTemplate.find(query2, User.class); list.forEach(System.out::println); }
使用 JSON 字符串方式查詢:
@Test public void testFindByJson() { // 等值查詢 Query query1 = new BasicQuery("{name:'eee'}"); // 多條件查詢 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 中無論是使用客戶端 API 還是使用 Spring Data,更新返回結(jié)果一定是受行數(shù)影響。如果更新后的結(jié)果和更新前的結(jié)果是相同,返回 0。
updateFirst()
:只更新滿足條件的第一條記錄。updateMulti()
:更新所有滿足條件的記錄。upsert()
:沒有符合條件的記錄則插入數(shù)據(jù)。
@Test public void test1() { Query query = new Query(Criteria.where("name").is("eee")); Update update = new Update(); update.set("age", 25); // updateFirst() 只更新滿足條件的第一條記錄 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() 更新所有滿足條件的記錄 UpdateResult updateResult = mongoTemplate.updateMulti(query, update, User.class); System.out.println("返回修改的記錄數(shù): " + updateResult.getModifiedCount()); }
@Test public void test3() { // query查詢結(jié)果不存在 Query query = new Query(Criteria.where("name").is("ggg")); Update update = new Update(); update.set("age", 28); update.setOnInsert("_id", 7); //不存在時(shí)插入 // upsert() 沒有符合條件的記錄則插入數(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 對象直接調(diào)用 aggregate,傳入聚合操作集合、表名、映射對象。
@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í)體類 接收結(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)建聚合操作對象,用預(yù)先生成的 MongoCollection 對象調(diào)用 aggregate 執(zhí)行。
@Test public void testAggregates(){ // 1.先通過集合名拿到所有文檔 MongoCollection<Document> collection = mongoTemplate.getCollection("book2"); // 2.Aggregates提供各種聚合操作符,返回一個(gè)Bson對象 Bson matchBson = Aggregates.match(new Document("type", "travel")); // Bson matchBson = Aggregates.match(Filters.eq("type", "travel"));//Filters來實(shí)現(xiàn)過濾 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ù)、平均收藏量
@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)表查詢用戶以及對應(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)表查詢訂單信息以及對應(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é)
本文是對MongoDB的學(xué)習(xí),SpringBoot整合MongoDB的SpringData,配置文件中如何連接,實(shí)體類如何映射到文檔,如何通過API進(jìn)行集合操作和文檔的增刪查改。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Spring注解實(shí)現(xiàn)Bean自動裝配示例詳解
這篇文章主要給大家介紹了關(guān)于Spring注解實(shí)現(xiàn)Bean自動裝配的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-03-03Java split函數(shù)拆分后變成null問題解決方案
這篇文章主要介紹了Java split函數(shù)拆分后變成null問題解決方案,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-10-10Spring Boot右鍵maven build成功但是直接運(yùn)行main方法出錯的解決方案
這篇文章主要介紹了Spring Boot-右鍵maven build成功但是直接運(yùn)行main方法出錯的解決方案,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-08-08mybatis-plus內(nèi)置雪花算法主鍵重復(fù)問題解決
本文主要介紹了mybatis-plus內(nèi)置雪花算法主鍵重復(fù)問題解決,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-09-09當(dāng)面試官問我ArrayList和LinkedList哪個(gè)更占空間時(shí),我是這么答的(面試官必問)
今天介紹一下Java的兩個(gè)集合類,ArrayList和LinkedList,這兩個(gè)集合的知識點(diǎn)幾乎可以說面試必問的。感興趣的朋友跟隨小編一起看看吧2020-08-08Spring boot 跳轉(zhuǎn)到j(luò)sp頁面的實(shí)現(xiàn)方法
本篇文章主要介紹了Spring boot 跳轉(zhuǎn)到j(luò)sp頁面的實(shí)現(xiàn)方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-04-04