SpringBoot 集成 Spring Data Mongodb 操作 MongoDB 详解
文章目录
!版权声明:本博客内容均为原创,每篇博文作为知识积累,写博不易,转载请注明出处。
系统环境:
- Java JDK 版本:1.8
- SpringBoot 版本:2.3.0.RELEASE
参考地址:
示例项目地址:
一、MongoDB 简介
MongoDB 是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,且与关系数据库的最为相像的。它支持的数据结构非常松散,是类似 json 的 bson 格式,因此可以存储比较复杂的数据类型。Mongo 最大的特点是它支持的查询语言非常强大,其语法有点类似于面向对象的查询语言,几乎可以实现类似关系数据库单表查询的绝大部分功能,而且还支持对数据建立索引。
二、MongoDB 特征
MongoDB 是一个文档数据库,它的数据以文档方式进行存储,将数据存储在类似 JSON 的 BSON 文档中,其特征如下:
- 数据以 BSON 方式存储
- 允许灵活和动态的模式。
- 支持数组和嵌套对象作为值。
- 处理数据的最自然,最有效的方式。
- 文档模型轻松映射到应用程序代码中的对象
- 强大的查询语言
- 支持聚合和其他现代用例,例如基于地理的搜索,图形搜索和文本搜索。
- 查询本身就是 JSON,因此很容易组合。不再需要串联字符串来动态生成 SQL 查询。
- 丰富而富有表现力的查询语言,无论您在文档中有多嵌套,都可以按任何字段进行过滤和排序。
- 拥有关系数据库的所有功能
- 支持查询联接。
- 具有快照隔离功能的分布式多文档 ACID 事务。
- 两种类型的关系,而不是一种"引用"和"嵌入式"。
- 分布式数据库为核心
- 水平扩展
- 内置了高可用性
- 地理分布并且易于使用
- MongoDB 免费使用
三、MongoDB 概念
简单介绍下 MongoDB 的概念知识,方便后续使用 SpringBoot 操作 MongoDB 时候对 MongoDB 相关概念知道其作用。
本文章并不是用于介绍 MongoDB 知识,而是介绍在 Java 语言中 SpringBoot 框架里如何操作 MongoDB。所以,在操作 MongoDB 前,最好对其知识点进行一下系统的学习。
1、基本概念
MongoDB 基本概念指的是学习 MongoDB 最先应该了解的词汇,比如 MongoDB 中的"数据库"、"集合"、"文档"这三个名词:
- 文档(Document): 文档是 MongoDB 中最基本的数据单元,由键值对组成,类似于 JSON 格式,可以存储不同字段,字段的值可以包括其他文档,数组和文档数组。
- 集合(Collection): 集合指的是文档组(类似于 Mysql 中的表的概念),里面可以存储许多文档。
- 数据库(Database): MongoDB 中可以存在多个数据库,每个数据库中中用有不同的集合与用户权限,这样可以供不同的项目组使用不同的数据库。
当然,还有其它一些概念,比如:
- _id(主键): 主键主要作用是用于保证数据完整性,加快数据库的访问速度,方便快速定位某个文档。在 MongoDB 中可以手动指定文档主键 ID,如果未手动指定则 MongoDB 会生成 12 位的 ObjectID。
- index(索引): 索引是一种特殊的数据结构,存储在一个易于遍历读取的数据集合中,其能够对数据库文档中的数据进行排序的一种结构。索引通常能极大提高文档查询效率,如果没有设置索引,MongoDB 会遍历集合中的整个文档,选取符合查询条件的文档记录。这种查询效率是非常低的,当处理大量时,查询可能需要花费几十秒甚至几分钟,这对网站的性能是非常致命的。
- field(字段): 文档中的字段,类似于关系型数据库中的列。
- aggregation(聚合) MongoDB 中聚合主要用于处理数据处理,例如统计平均值、求和等,可以快速通过聚合操作,汇总数据,尤其是对绘制图表添加了便利。
2、数据类型
以下为 MongoDB 中常用的几种数据类型:
- String: 字符串,存储数据常用的数据类型。在 MongoDB 中,UTF-8 编码的字符串才是合法的。
- Integer: 整型数值,用于存储数值。根据你所采用的服务器,可分为 32 位或 64 位。
- Boolean: 布尔值,用于存储布尔值(true/false)。
- Double: 双精度浮点值,用于存储浮点值。
- Min/Max keys: 将一个值与 BSON(二进制的 JSON)元素的最低值和最高值相对比。
- Array: 用于将数组或列表或多个值存储为一个键。
- Timestamp: 时间戳。记录文档修改或添加的具体时间。
- Object: 用于内嵌文档。
- Null: 用于创建空值。
- Symbol: 符号。该数据类型基本上等同于字符串类型,但不同的是,它一般用于采用特殊符号类型的语言。
- Date: 日期时间,用 UNIX 时间格式来存储当前日期或时间。你可以指定自己的日期时间:创建 Date 对象,传入年月日信息。
- Object ID: 对象 ID,用于创建文档的 ID。
- Binary Data: 二进制数据,用于存储二进制数据。
- Code: 代码类型,用于在文档中存储 JavaScript 代码。
- Regular expression: 正则表达式类型,用于存储正则表达式。
四、Springboot 操作 MongoDB 示例
这里使用 Spring Data MongoDB 封装的 MongoDB 官方 Java 驱动 MongoTemplate 对 MongoDB 进行操作。
关于使用简单的 Repositories 方式来操作 MongoDB 这种用法只能实现较简单的操作,使用简单但是灵活性比较差,所以这里就不介绍这种使用方式了。
1、Maven 引入相关依赖
Maven 引入 SpringBoot 和 MongoDB 相关依赖组件:
1<?xml version="1.0" encoding="UTF-8"?>
2<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
4 <modelVersion>4.0.0</modelVersion>
5
6 <parent>
7 <groupId>org.springframework.boot</groupId>
8 <artifactId>spring-boot-starter-parent</artifactId>
9 <version>2.3.0.RELEASE</version>
10 </parent>
11
12 <groupId>mydlq.club</groupId>
13 <artifactId>springboot-mongodb-template-example</artifactId>
14 <version>0.0.1</version>
15 <name>springboot-mongodb-template-example</name>
16 <description>Demo project for Spring Boot MongoDB</description>
17
18 <properties>
19 <java.version>1.8</java.version>
20 </properties>
21
22 <dependencies>
23 <!-- SpringBoot Web -->
24 <dependency>
25 <groupId>org.springframework.boot</groupId>
26 <artifactId>spring-boot-starter-web</artifactId>
27 </dependency>
28 <!-- Lombok -->
29 <dependency>
30 <groupId>org.projectlombok</groupId>
31 <artifactId>lombok</artifactId>
32 <scope>provided</scope>
33 </dependency>
34 <!-- SpringBoot MongoDB -->
35 <dependency>
36 <groupId>org.springframework.boot</groupId>
37 <artifactId>spring-boot-starter-data-mongodb</artifactId>
38 </dependency>
39 </dependencies>
40
41 <build>
42 <plugins>
43 <plugin>
44 <groupId>org.springframework.boot</groupId>
45 <artifactId>spring-boot-maven-plugin</artifactId>
46 </plugin>
47 </plugins>
48 </build>
49
50</project>
依赖说明:
- spring-boot-starter-web: SpringBoot 的 Web 依赖。
- lombok: Lombok 工具依赖,便于生成实体对象的 Get 与 Set 方法。
- spring-boot-starter-data-mongodb:Spring 对 MongoDb 提供的 Java Drive 封装的框架。
2、Application 文件中添加 MongoDB 连接配置
在 SpringBoot 的 application.yml 文件中添加连接 MongoDB 的配置参数,内容如下:
1spring:
2 data:
3 mongodb:
4 host: 127.0.0.1
5 port: 27017
6 database: test
7 username: admin
8 password: 123456
参数介绍:
- spring.data.mongodb.host: 指定 MongoDB Server 地址
- spring.data.mongodb.port: 指定 MongoDB Server 端口
- spring.data.mongodb.database: 指定使用的数据库
- spring.data.mongodb.username: MongoDB 用户名
- spring.data.mongodb.password: MongoDB 密码
3、创建用于测试的实体类
创建用于示例中测试的实体 User 和 Status 类:
User.java
1import com.fasterxml.jackson.annotation.JsonFormat;
2import lombok.Data;
3import lombok.ToString;
4import lombok.experimental.Accessors;
5import org.springframework.data.mongodb.core.mapping.MongoId;
6import java.util.Date;
7
8@Data
9@ToString
10@Accessors(chain = true)
11public class User {
12
13 /**
14 * 使用 @MongoID 能更清晰的指定 _id 主键
15 */
16 @MongoId
17 private String id;
18 private String name;
19 private String sex;
20 private Integer salary;
21 private Integer age;
22 @JsonFormat( pattern ="yyyy-MM-dd", timezone ="GMT+8")
23 private Date birthday;
24 private String remake;
25 private Status status;
26
27}
使用 Lombok 中的 @Accessors(chain = true) 注解,能让我们方便使用链式方法创建实体对象。
Status.java
1import lombok.Data;
2import lombok.ToString;
3import lombok.experimental.Accessors;
4
5@Data
6@ToString
7@Accessors(chain = true)
8public class Status {
9
10 private Integer weight;
11 private Integer height;
12
13}
4、SpringBoot 启动类
创建 SpringBoot 启动类,方便测试:
1import org.springframework.boot.SpringApplication;
2import org.springframework.boot.autoconfigure.SpringBootApplication;
3import springfox.documentation.swagger2.annotations.EnableSwagger2;
4
5@EnableSwagger2
6@SpringBootApplication
7public class Application {
8
9 public static void main(String[] args) {
10 SpringApplication.run(Application.class, args);
11 }
12
13}
5、MongoDB 集合操作
(1)、创建集合
示例代码如下:
1import org.springframework.data.mongodb.core.CollectionOptions;
2import org.springframework.data.mongodb.core.MongoTemplate;
3import org.springframework.data.mongodb.core.query.Criteria;
4import org.springframework.data.mongodb.core.query.CriteriaDefinition;
5import org.springframework.data.mongodb.core.validation.Validator;
6import org.springframework.stereotype.Service;
7import javax.annotation.Resource;
8
9@Service
10public class CreateCollectionService {
11
12 @Resource
13 private MongoTemplate mongoTemplate;
14
15 /**
16 * 创建【集合】
17 *
18 * 创建一个大小没有限制的集合(默认集合创建方式)
19 *
20 * @return 创建集合的结果
21 */
22 public Object createCollection() {
23 // 设置集合名称
24 String collectionName = "users1";
25 // 创建集合并返回集合信息
26 mongoTemplate.createCollection(collectionName);
27 // 检测新的集合是否存在,返回创建结果
28 return mongoTemplate.collectionExists(collectionName) ? "创建视图成功" : "创建视图失败";
29 }
30
31 /**
32 * 创建【固定大小集合】
33 *
34 * 创建集合并设置 `capped=true` 创建 `固定大小集合`,可以配置参数 `size` 限制文档大小,可以配置参数 `max` 限制集合文档数量。
35 *
36 * @return 创建集合的结果
37 */
38 public Object createCollectionFixedSize() {
39 // 设置集合名称
40 String collectionName = "users2";
41 // 设置集合参数
42 long size = 1024L;
43 long max = 5L;
44 // 创建固定大小集合
45 CollectionOptions collectionOptions = CollectionOptions.empty()
46 // 创建固定集合。固定集合是指有着固定大小的集合,当达到最大值时,它会自动覆盖最早的文档。
47 .capped()
48 // 固定集合指定一个最大值,以千字节计(KB),如果 capped 为 true,也需要指定该字段。
49 .size(size)
50 // 指定固定集合中包含文档的最大数量。
51 .maxDocuments(max);
52 // 执行创建集合
53 mongoTemplate.createCollection(collectionName, collectionOptions);
54 // 检测新的集合是否存在,返回创建结果
55 return mongoTemplate.collectionExists(collectionName) ? "创建视图成功" : "创建视图失败";
56 }
57
58 /**
59 * 创建【验证文档数据】的集合
60 *
61 * 创建集合并在文档"插入"与"更新"时进行数据效验,如果符合创建集合设置的条件就进允许更新与插入,否则则按照设置的设置的策略进行处理。
62 *
63 * * 效验级别:
64 * - off:关闭数据校验。
65 * - strict:(默认值) 对所有的文档"插入"与"更新"操作有效。
66 * - moderate:仅对"插入"和满足校验规则的"文档"做"更新"操作有效。对已存在的不符合校验规则的"文档"无效。
67 * * 执行策略:
68 * - error:(默认值) 文档必须满足校验规则,才能被写入。
69 * - warn:对于"文档"不符合校验规则的 MongoDB 允许写入,但会记录一条告警到 mongod.log 中去。日志内容记录报错信息以及该"文档"的完整记录。
70 *
71 * @return 创建集合结果
72 */
73 public Object createCollectionValidation() {
74 // 设置集合名称
75 String collectionName = "users3";
76 // 设置验证条件,只允许岁数大于20的用户信息插入
77 CriteriaDefinition criteria = Criteria.where("age").gt(20);
78 // 设置集合选项验证对象
79 CollectionOptions collectionOptions = CollectionOptions.empty()
80 .validator(Validator.criteria(criteria))
81 // 设置效验级别
82 .strictValidation()
83 // 设置效验不通过后执行的动作
84 .failOnValidationError();
85 // 执行创建集合
86 mongoTemplate.createCollection(collectionName, collectionOptions);
87 // 检测新的集合是否存在,返回创建结果
88 return mongoTemplate.collectionExists(collectionName) ? "创建集合成功" : "创建集合失败";
89 }
90
91}
(2)、查询集合
1import org.springframework.data.mongodb.core.MongoTemplate;
2import org.springframework.stereotype.Service;
3import javax.annotation.Resource;
4
5@Service
6public class QueryCollectionService {
7
8 @Resource
9 private MongoTemplate mongoTemplate;
10
11 /**
12 * 获取【集合名称】列表
13 *
14 * @return 集合名称列表
15 */
16 public Object getCollectionNames() {
17 // 执行获取集合名称列表
18 return mongoTemplate.getCollectionNames();
19 }
20
21 /**
22 * 检测集合【是否存在】
23 *
24 * @return 集合是否存在
25 */
26 public boolean collectionExists() {
27 // 设置集合名称
28 String collectionName = "users";
29 // 检测新的集合是否存在,返回检测结果
30 return mongoTemplate.collectionExists(collectionName);
31 }
32
33}
(3)、删除集合
1import org.springframework.data.mongodb.core.MongoTemplate;
2import org.springframework.stereotype.Service;
3import javax.annotation.Resource;
4
5@Service
6public class RemoveCollectionService {
7
8 @Resource
9 private MongoTemplate mongoTemplate;
10
11 /**
12 * 删除【集合】
13 *
14 * @return 创建集合结果
15 */
16 public Object dropCollection() {
17 // 设置集合名称
18 String collectionName = "users3";
19 // 执行删除集合
20 mongoTemplate.getCollection(collectionName).drop();
21 // 检测新的集合是否存在,返回删除结果
22 return !mongoTemplate.collectionExists(collectionName) ? "删除集合成功" : "删除集合失败";
23 }
24
25}
6、MongoDB 视图操作
1import org.bson.Document;
2import org.bson.conversions.Bson;
3import org.springframework.data.mongodb.core.MongoTemplate;
4import org.springframework.stereotype.Service;
5import javax.annotation.Resource;
6import java.util.ArrayList;
7import java.util.List;
8
9@Service
10public class ViewService {
11
12 @Resource
13 private MongoTemplate mongoTemplate;
14
15 /**
16 * 创建视图
17 *
18 * @return 创建视图结果
19 */
20 public Object createView() {
21 // 设置视图名
22 String newViewName = "usersView";
23 // 设置获取数据的集合名称
24 String collectionName = "users";
25 // 定义视图的管道,可是设置视图显示的内容多个筛选条件
26 List<Bson> pipeline = new ArrayList<>();
27 // 设置条件,用于筛选集合中的文档数据,只有符合条件的才会映射到视图中
28 pipeline.add(Document.parse("{\"$match\":{\"sex\":\"女\"}}"));
29 // 执行创建视图
30 mongoTemplate.getDb().createView(newViewName, collectionName, pipeline);
31 // 检测新的集合是否存在,返回创建结果
32 return mongoTemplate.collectionExists(newViewName) ? "创建视图成功" : "创建视图失败";
33 }
34
35 /**
36 * 删除视图
37 *
38 * @return 删除视图结果
39 */
40 public Object dropView() {
41 // 设置待删除的视图名称
42 String viewName = "usersView";
43 // 检测视图是否存在
44 if (mongoTemplate.collectionExists(viewName)) {
45 // 删除视图
46 mongoTemplate.getDb().getCollection(viewName).drop();
47 return "删除视图成功";
48 }
49 // 检测新的集合是否存在,返回创建结果
50 return !mongoTemplate.collectionExists(viewName) ? "删除视图成功" : "删除视图失败";
51 }
52
53}
7、MongoDB 文档操作
(1)、文档插入
1import lombok.extern.slf4j.Slf4j;
2import mydlq.club.example.entity.Status;
3import mydlq.club.example.entity.User;
4import org.springframework.data.mongodb.core.MongoTemplate;
5import org.springframework.stereotype.Service;
6import javax.annotation.Resource;
7import java.util.ArrayList;
8import java.util.Collection;
9import java.util.Date;
10import java.util.List;
11
12@Slf4j
13@Service
14public class InsertService {
15
16 /** 设置集合名称 */
17 private static final String COLLECTION_NAME = "users";
18
19 @Resource
20 private MongoTemplate mongoTemplate;
21
22 /**
23 * 插入【一条】文档数据,如果文档信息已经【存在就抛出异常】
24 *
25 * @return 插入的文档信息
26 */
27 public Object insert() {
28 // 设置用户信息
29 User user = new User()
30 .setId("10")
31 .setAge(22)
32 .setSex("男")
33 .setRemake("无")
34 .setSalary(1500)
35 .setName("zhangsan")
36 .setBirthday(new Date())
37 .setStatus(new Status().setHeight(180).setWeight(150));
38 // 插入一条用户数据,如果文档信息已经存在就抛出异常
39 User newUser = mongoTemplate.insert(user, COLLECTION_NAME);
40 // 输出存储结果
41 log.info("存储的用户信息为:{}", newUser);
42 return newUser;
43 }
44
45 /**
46 * 插入【多条】文档数据,如果文档信息已经【存在就抛出异常】
47 *
48 * @return 插入的多个文档信息
49 *
50 */
51 public Object insertMany(){
52 // 设置两个用户信息
53 User user1 = new User()
54 .setId("11")
55 .setAge(22)
56 .setSex("男")
57 .setRemake("无")
58 .setSalary(1500)
59 .setName("shiyi")
60 .setBirthday(new Date())
61 .setStatus(new Status().setHeight(180).setWeight(150));
62 User user2 = new User()
63 .setId("12")
64 .setAge(22)
65 .setSex("男")
66 .setRemake("无")
67 .setSalary(1500)
68 .setName("shier")
69 .setBirthday(new Date())
70 .setStatus(new Status().setHeight(180).setWeight(150));
71 // 使用户信息加入结合
72 List<User> userList = new ArrayList<>();
73 userList.add(user1);
74 userList.add(user2);
75 // 插入一条用户数据,如果某个文档信息已经存在就抛出异常
76 Collection<User> newUserList = mongoTemplate.insert(userList, COLLECTION_NAME);
77 // 输出存储结果
78 for (User user : newUserList) {
79 log.info("存储的用户信息为:{}", user);
80 }
81 return newUserList;
82 }
83
84}
(2)、文档存储
1import lombok.extern.slf4j.Slf4j;
2import mydlq.club.example.entity.Status;
3import mydlq.club.example.entity.User;
4import org.springframework.data.mongodb.core.MongoTemplate;
5import org.springframework.stereotype.Service;
6import javax.annotation.Resource;
7import java.util.Date;
8
9@Slf4j
10@Service
11public class SaveService {
12
13 /** 设置集合名称 */
14 private static final String COLLECTION_NAME = "users";
15
16 @Resource
17 private MongoTemplate mongoTemplate;
18
19 /**
20 * 存储【一条】用户信息,如果文档信息已经【存在就执行更新】
21 *
22 * @return 存储的文档信息
23 */
24 public Object save() {
25 // 设置用户信息
26 User user = new User()
27 .setId("13")
28 .setAge(22)
29 .setSex("男")
30 .setRemake("无")
31 .setSalary(2800)
32 .setName("kuiba")
33 .setBirthday(new Date())
34 .setStatus(new Status().setHeight(169).setWeight(150));
35 // 存储用户信息,如果文档信息已经存在就执行更新
36 User newUser = mongoTemplate.save(user, COLLECTION_NAME);
37 // 输出存储结果
38 log.info("存储的用户信息为:{}", newUser);
39 return newUser;
40 }
41
42}
(3)、文档查询
1import lombok.extern.slf4j.Slf4j;
2import mydlq.club.example.entity.User;
3import org.springframework.data.domain.Sort;
4import org.springframework.data.mongodb.core.MongoTemplate;
5import org.springframework.data.mongodb.core.query.Criteria;
6import org.springframework.data.mongodb.core.query.Query;
7import org.springframework.stereotype.Service;
8import javax.annotation.Resource;
9import java.util.Arrays;
10import java.util.List;
11
12@Slf4j
13@Service
14public class QueryService {
15
16 /**
17 * 设置集合名称
18 */
19 private static final String COLLECTION_NAME = "users";
20
21 @Resource
22 private MongoTemplate mongoTemplate;
23
24 /**
25 * 查询集合中的【全部】文档数据
26 *
27 * @return 全部文档列表
28 */
29 public Object findAll() {
30 // 执行查询集合中全部文档信息
31 List<User> documentList = mongoTemplate.findAll(User.class, COLLECTION_NAME);
32 // 输出结果
33 for (User user : documentList) {
34 log.info("用户信息:{}", user);
35 }
36 return documentList;
37 }
38
39 /**
40 * 根据【文档ID】查询集合中文档数据
41 *
42 * @return 文档信息
43 */
44 public Object findById() {
45 // 设置查询的文档 ID
46 String id = "1";
47 // 根据文档ID查询集合中文档数据,并转换为对应 Java 对象
48 User user = mongoTemplate.findById(id, User.class, COLLECTION_NAME);
49 // 输出结果
50 log.info("用户信息:{}", user);
51 return user;
52 }
53
54 /**
55 * 根据【条件】查询集合中【符合条件】的文档,只取【第一条】数据
56 *
57 * @return 符合条件的第一条文档
58 */
59 public Object findOne() {
60 // 设置查询条件参数
61 int age = 22;
62 // 创建条件对象
63 Criteria criteria = Criteria.where("age").is(age);
64 // 创建查询对象,然后将条件对象添加到其中
65 Query query = new Query(criteria);
66 // 查询一条文档,如果查询结果中有多条文档,那么就取第一条
67 User user = mongoTemplate.findOne(query, User.class, COLLECTION_NAME);
68 // 输出结果
69 log.info("用户信息:{}", user);
70 return user;
71 }
72
73 /**
74 * 根据【条件】查询集合中【符合条件】的文档,获取其【文档列表】
75 *
76 * @return 符合条件的文档列表
77 */
78 public Object findByCondition() {
79 // 设置查询条件参数
80 String sex = "女";
81 // 创建条件对象
82 Criteria criteria = Criteria.where("sex").is(sex);
83 // 创建查询对象,然后将条件对象添加到其中
84 Query query = new Query(criteria);
85 // 查询并返回结果
86 List<User> documentList = mongoTemplate.find(query, User.class, COLLECTION_NAME);
87 // 输出结果
88 for (User user : documentList) {
89 log.info("用户信息:{}", user);
90 }
91 return documentList;
92 }
93
94 /**
95 * 根据【条件】查询集合中【符合条件】的文档,获取其【文档列表】并【排序】
96 *
97 * @return 符合条件的文档列表
98 */
99 public Object findByConditionAndSort() {
100 // 设置查询条件参数
101 String sex = "男";
102 String sort = "age";
103 // 创建条件对象
104 Criteria criteria = Criteria.where("sex").is(sex);
105 // 创建查询对象,然后将条件对象添加到其中,然后根据指定字段进行排序
106 Query query = new Query(criteria).with(Sort.by(sort));
107 // 执行查询
108 List<User> documentList = mongoTemplate.find(query, User.class, COLLECTION_NAME);
109 // 输出结果
110 for (User user : documentList) {
111 log.info("用户信息:{}", user);
112 }
113 return documentList;
114 }
115
116 /**
117 * 根据【单个条件】查询集合中的文档数据,并【按指定字段进行排序】与【限制指定数目】
118 *
119 * @return 符合条件的文档列表
120 */
121 public Object findByConditionAndSortLimit() {
122 // 设置查询条件参数
123 String sex = "男";
124 String sort = "age";
125 int limit = 2;
126 // 创建条件对象
127 Criteria criteria = Criteria.where("sex").is(sex);
128 // 创建查询对象,然后将条件对象添加到其中
129 Query query = new Query(criteria).with(Sort.by(sort)).limit(limit);
130 // 执行查询
131 List<User> documentList = mongoTemplate.find(query, User.class, COLLECTION_NAME);
132 // 输出结果
133 for (User user : documentList) {
134 log.info("用户信息:{}", user);
135 }
136 return documentList;
137 }
138
139 /**
140 * 根据【单个条件】查询集合中的文档数据,并【按指定字段进行排序】与【并跳过指定数目】
141 *
142 * @return 符合条件的文档列表
143 */
144 public Object findByConditionAndSortSkip() {
145 // 设置查询条件参数
146 String sex = "男";
147 String sort = "age";
148 int skip = 1;
149 // 创建条件对象
150 Criteria criteria = Criteria.where("sex").is(sex);
151 // 创建查询对象,然后将条件对象添加到其中
152 Query query = new Query(criteria).with(Sort.by(sort)).skip(skip);
153 // 查询并返回结果
154 List<User> documentList = mongoTemplate.find(query, User.class, COLLECTION_NAME);
155 // 输出结果
156 for (User user : documentList) {
157 log.info("用户信息:{}", user);
158 }
159 return documentList;
160 }
161
162 /**
163 * 查询【存在指定字段名称】的文档数据
164 *
165 * @return 符合条件的文档列表
166 */
167 public Object findByExistsField() {
168 // 设置查询条件参数
169 String field = "sex";
170 // 创建条件
171 Criteria criteria = Criteria.where(field).exists(true);
172 // 创建查询对象,然后将条件对象添加到其中
173 Query query = new Query(criteria);
174 // 查询并返回结果
175 List<User> documentList = mongoTemplate.find(query, User.class, COLLECTION_NAME);
176 // 输出结果
177 for (User user : documentList) {
178 log.info("用户信息:{}", user);
179 }
180 return documentList;
181 }
182
183 /**
184 * 根据【AND】关联多个查询条件,查询集合中的文档数据
185 *
186 * @return 符合条件的文档列表
187 */
188 public Object findByAndCondition() {
189 // 设置查询条件参数
190 String sex = "男";
191 Integer age = 22;
192 // 创建条件
193 Criteria criteriaSex = Criteria.where("sex").is(sex);
194 Criteria criteriaAge = Criteria.where("age").is(age);
195 // 创建条件对象,将上面条件进行 AND 关联
196 Criteria criteria = new Criteria().andOperator(criteriaSex, criteriaAge);
197 // 创建查询对象,然后将条件对象添加到其中
198 Query query = new Query(criteria);
199 // 查询并返回结果
200 List<User> documentList = mongoTemplate.find(query, User.class, COLLECTION_NAME);
201 // 输出结果
202 for (User user : documentList) {
203 log.info("用户信息:{}", user);
204 }
205 return documentList;
206 }
207
208 /**
209 * 根据【OR】关联多个查询条件,查询集合中的文档数据
210 *
211 * @return 符合条件的文档列表
212 */
213 public Object findByOrCondition() {
214 // 设置查询条件参数
215 String sex = "男";
216 int age = 22;
217 // 创建条件
218 Criteria criteriaSex = Criteria.where("sex").is(sex);
219 Criteria criteriaAge = Criteria.where("age").is(age);
220 // 创建条件对象,将上面条件进行 OR 关联
221 Criteria criteria = new Criteria().orOperator(criteriaSex, criteriaAge);
222 // 创建查询对象,然后将条件对象添加到其中
223 Query query = new Query(criteria);
224 // 查询并返回结果
225 List<User> documentList = mongoTemplate.find(query, User.class, COLLECTION_NAME);
226 // 输出结果
227 for (User user : documentList) {
228 log.info("用户信息:{}", user);
229 }
230 return documentList;
231 }
232
233 /**
234 * 根据【IN】关联多个查询条件,查询集合中的文档数据
235 *
236 * @return 符合条件的文档列表
237 */
238 public Object findByInCondition() {
239 // 设置查询条件参数
240 Integer[] ages = {20, 22, 25};
241 // 创建条件
242 List<Integer> ageList = Arrays.asList(ages);
243 // 创建条件对象
244 Criteria criteria = Criteria.where("age").in(ageList);
245 // 创建查询对象,然后将条件对象添加到其中
246 Query query = new Query(criteria);
247 // 查询并返回结果
248 List<User> documentList = mongoTemplate.find(query, User.class, COLLECTION_NAME);
249 // 输出结果
250 for (User user : documentList) {
251 log.info("用户信息:{}", user);
252 }
253 return documentList;
254 }
255
256 /**
257 * 根据【逻辑运算符】查询集合中的文档数据
258 *
259 * @return 符合条件的文档列表
260 */
261 public Object findByOperator() {
262 // 设置查询条件参数
263 int min = 25;
264 int max = 35;
265 // 创建条件对象
266 Criteria criteria = Criteria.where("age").gt(min).lte(max);
267 // 创建查询对象,然后将条件对象添加到其中
268 Query query = new Query(criteria);
269 // 查询并返回结果
270 List<User> documentList = mongoTemplate.find(query, User.class, COLLECTION_NAME);
271 // 输出结果
272 for (User user : documentList) {
273 log.info("用户信息:{}", user);
274 }
275 return documentList;
276 }
277
278 /**
279 * 根据【正则表达式】查询集合中的文档数据
280 *
281 * @return 符合条件的文档列表
282 */
283 public Object findByRegex() {
284 // 设置查询条件参数
285 String regex = "^zh*";
286 // 创建条件对象
287 Criteria criteria = Criteria.where("name").regex(regex);
288 // 创建查询对象,然后将条件对象添加到其中
289 Query query = new Query(criteria);
290 // 查询并返回结果
291 List<User> documentList = mongoTemplate.find(query, User.class, COLLECTION_NAME);
292 // 输出结果
293 for (User user : documentList) {
294 log.info("用户信息:{}", user);
295 }
296 return documentList;
297 }
298
299 /**
300 * 统计集合中符合【查询条件】的文档【数量】
301 *
302 * @return 符合条件的文档列表
303 */
304 public Object countNumber() {
305 // 设置查询条件参数
306 int age = 22;
307 // 创建条件对象
308 Criteria criteria = Criteria.where("age").is(age);
309 // 创建查询对象,然后将条件对象添加到其中
310 Query query = new Query(criteria);
311 // 查询并返回结果
312 long count = mongoTemplate.count(query, User.class, COLLECTION_NAME);
313 // 输出结果
314 log.info("符合条件的文档数量:{}", count);
315 return count;
316 }
317
318}
(4)、文档更新
1import com.mongodb.client.result.UpdateResult;
2import lombok.extern.slf4j.Slf4j;
3import mydlq.club.example.entity.User;
4import org.springframework.data.domain.Sort;
5import org.springframework.data.mongodb.core.MongoTemplate;
6import org.springframework.data.mongodb.core.query.Criteria;
7import org.springframework.data.mongodb.core.query.Query;
8import org.springframework.data.mongodb.core.query.Update;
9import org.springframework.stereotype.Service;
10import javax.annotation.Resource;
11
12@Slf4j
13@Service
14public class UpdateService {
15
16 /**
17 * 设置集合名称
18 */
19 private static final String COLLECTION_NAME = "users";
20
21 @Resource
22 private MongoTemplate mongoTemplate;
23
24 /**
25 * 更新集合中【匹配】查询到的第一条文档数据,如果没有找到就【创建并插入一个新文档】
26 *
27 * @return 执行更新的结果
28 */
29 public Object update() {
30 // 创建条件对象
31 Criteria criteria = Criteria.where("age").is(30);
32 // 创建查询对象,然后将条件对象添加到其中
33 Query query = new Query(criteria);
34 // 创建更新对象,并设置更新的内容
35 Update update = new Update().set("age", 33).set("name", "zhangsansan");
36 // 执行更新,如果没有找到匹配查询的文档,则创建并插入一个新文档
37 UpdateResult result = mongoTemplate.upsert(query, update, User.class, COLLECTION_NAME);
38 // 输出结果信息
39 String resultInfo = "匹配到" + result.getMatchedCount() + "条数据,对第一条数据进行了更改";
40 log.info("更新结果:{}", resultInfo);
41 return resultInfo;
42 }
43
44 /**
45 * 更新集合中【匹配】查询到的【文档数据集合】中的【第一条数据】
46 *
47 * @return 执行更新的结果
48 */
49 public Object updateFirst() {
50 // 创建条件对象
51 Criteria criteria = Criteria.where("name").is("zhangsan");
52 // 创建查询对象,然后将条件对象添加到其中,并设置排序
53 Query query = new Query(criteria).with(Sort.by("age").ascending());
54 // 创建更新对象,并设置更新的内容
55 Update update = new Update().set("age", 30).set("name", "zhangsansan");
56 // 执行更新
57 UpdateResult result = mongoTemplate.updateFirst(query, update, User.class, COLLECTION_NAME);
58 // 输出结果信息
59 String resultInfo = "共匹配到" + result.getMatchedCount() + "条数据,修改了" + result.getModifiedCount() + "条数据";
60 log.info("更新结果:{}", resultInfo);
61 return resultInfo;
62 }
63
64 /**
65 * 更新【匹配查询】到的【文档数据集合】中的【所有数据】
66 *
67 * @return 执行更新的结果
68 */
69 public Object updateMany() {
70 // 创建条件对象
71 Criteria criteria = Criteria.where("age").gt(28);
72 // 创建查询对象,然后将条件对象添加到其中
73 Query query = new Query(criteria);
74 // 设置更新字段和更新的内容
75 Update update = new Update().set("age", 29).set("salary", "1999");
76 // 执行更新
77 UpdateResult result = mongoTemplate.updateMulti(query, update, User.class, COLLECTION_NAME);
78 // 输出结果信息
79 String resultInfo = "总共匹配到" + result.getMatchedCount() + "条数据,修改了" + result.getModifiedCount() + "条数据";
80 log.info("更新结果:{}", resultInfo);
81 return resultInfo;
82 }
83
84}
(5)、文档删除
1import com.mongodb.client.result.DeleteResult;
2import lombok.extern.slf4j.Slf4j;
3import mydlq.club.example.entity.User;
4import org.springframework.data.mongodb.core.MongoTemplate;
5import org.springframework.data.mongodb.core.query.Criteria;
6import org.springframework.data.mongodb.core.query.Query;
7import org.springframework.stereotype.Service;
8import javax.annotation.Resource;
9import java.util.List;
10
11@Slf4j
12@Service
13public class RemoveService {
14
15 /**
16 * 设置集合名称
17 */
18 private static final String COLLECTION_NAME = "users";
19
20 @Resource
21 private MongoTemplate mongoTemplate;
22
23 /**
24 * 删除集合中【符合条件】的【一个]或[多个】文档
25 *
26 * @return 删除用户信息的结果
27 */
28 public Object remove() {
29 // 设置查询条件参数
30 int age = 30;
31 String sex = "男";
32 // 创建条件对象
33 Criteria criteria = Criteria.where("age").is(age).and("sex").is(sex);
34 // 创建查询对象,然后将条件对象添加到其中
35 Query query = new Query(criteria);
36 // 执行删除查找到的匹配的全部文档信息
37 DeleteResult result = mongoTemplate.remove(query, COLLECTION_NAME);
38 // 输出结果信息
39 String resultInfo = "成功删除 " + result.getDeletedCount() + " 条文档信息";
40 log.info(resultInfo);
41 return resultInfo;
42 }
43
44 /**
45 * 删除【符合条件】的【单个文档】,并返回删除的文档。
46 *
47 * @return 删除的用户信息
48 */
49 public Object findAndRemove() {
50 // 设置查询条件参数
51 String name = "zhangsansan";
52 // 创建条件对象
53 Criteria criteria = Criteria.where("name").is(name);
54 // 创建查询对象,然后将条件对象添加到其中
55 Query query = new Query(criteria);
56 // 执行删除查找到的匹配的第一条文档,并返回删除的文档信息
57 User result = mongoTemplate.findAndRemove(query, User.class, COLLECTION_NAME);
58 // 输出结果信息
59 String resultInfo = "成功删除文档信息,文档内容为:" + result;
60 log.info(resultInfo);
61 return result;
62 }
63
64 /**
65 * 删除【符合条件】的【全部文档】,并返回删除的文档。
66 *
67 * @return 删除的全部用户信息
68 */
69 public Object findAllAndRemove() {
70 // 设置查询条件参数
71 int age = 22;
72 // 创建条件对象
73 Criteria criteria = Criteria.where("age").is(age);
74 // 创建查询对象,然后将条件对象添加到其中
75 Query query = new Query(criteria);
76 // 执行删除查找到的匹配的全部文档,并返回删除的全部文档信息
77 List<User> resultList = mongoTemplate.findAllAndRemove(query, User.class, COLLECTION_NAME);
78 // 输出结果信息
79 String resultInfo = "成功删除文档信息,文档内容为:" + resultList;
80 log.info(resultInfo);
81 return resultList;
82 }
83
84}
8、MongoDB 聚合操作
(1)、聚合表达式
1import lombok.extern.slf4j.Slf4j;
2import org.springframework.data.domain.Sort;
3import org.springframework.data.mongodb.core.MongoTemplate;
4import org.springframework.data.mongodb.core.aggregation.Aggregation;
5import org.springframework.data.mongodb.core.aggregation.AggregationOperation;
6import org.springframework.data.mongodb.core.aggregation.AggregationResults;
7import org.springframework.stereotype.Service;
8import javax.annotation.Resource;
9import java.util.Map;
10
11/**
12 * 聚合表达式 $group
13 *
14 * @author mydlq
15 */
16@Slf4j
17@Service
18public class AggregateGroupService {
19
20 /**
21 * 设置集合名称
22 */
23 private static final String COLLECTION_NAME = "users";
24
25 @Resource
26 private MongoTemplate mongoTemplate;
27
28 /**
29 * 使用管道操作符 $group 结合 $count 方法进行聚合统计
30 *
31 * @return 聚合结果
32 */
33 public Object aggregationGroupCount() {
34 // 使用管道操作符 $group 进行分组,然后统计各个组的文档数量
35 AggregationOperation group = Aggregation.group("age").count().as("numCount");
36 // 将操作加入到聚合对象中
37 Aggregation aggregation = Aggregation.newAggregation(group);
38 // 执行聚合查询
39 AggregationResults<Map> results = mongoTemplate.aggregate(aggregation, COLLECTION_NAME, Map.class);
40 for (Map result : results.getMappedResults()) {
41 log.info("{}", result);
42 }
43 return results.getMappedResults();
44 }
45
46 /**
47 * 使用管道操作符 $group 结合表达式操作符 $max 进行聚合统计
48 *
49 * @return 聚合结果
50 */
51 public Object aggregationGroupMax() {
52 // 使用管道操作符 $group 进行分组,然后统计各个组文档某字段最大值
53 AggregationOperation group = Aggregation.group("sex").max("salary").as("salaryMax");
54 // 将操作加入到聚合对象中
55 Aggregation aggregation = Aggregation.newAggregation(group);
56 // 执行聚合查询
57 AggregationResults<Map> results = mongoTemplate.aggregate(aggregation, COLLECTION_NAME, Map.class);
58 for (Map result : results.getMappedResults()) {
59 log.info("{}", result);
60 }
61 return results.getMappedResults();
62 }
63
64 /**
65 * 使用管道操作符 $group 结合表达式操作符 $min 进行聚合统计
66 *
67 * @return 聚合结果
68 */
69 public Object aggregationGroupMin() {
70 // 使用管道操作符 $group 进行分组,然后统计各个组文档某字段最小值
71 AggregationOperation group = Aggregation.group("sex").min("salary").as("salaryMin");
72 // 将操作加入到聚合对象中
73 Aggregation aggregation = Aggregation.newAggregation(group);
74 // 执行聚合查询
75 AggregationResults<Map> results = mongoTemplate.aggregate(aggregation, COLLECTION_NAME, Map.class);
76 for (Map result : results.getMappedResults()) {
77 log.info("{}", result);
78 }
79 return results.getMappedResults();
80 }
81
82 /**
83 * 使用管道操作符 $group 结合表达式操作符 $sum 进行聚合统计
84 *
85 * @return 聚合结果
86 */
87 public Object aggregationGroupSum() {
88 // 使用管道操作符 $group 进行分组,然后统计各个组文档某字段值合计
89 AggregationOperation group = Aggregation.group("sex").sum("salary").as("salarySum");
90 // 将操作加入到聚合对象中
91 Aggregation aggregation = Aggregation.newAggregation(group);
92 // 执行聚合查询
93 AggregationResults<Map> results = mongoTemplate.aggregate(aggregation, COLLECTION_NAME, Map.class);
94 for (Map result : results.getMappedResults()) {
95 log.info("{}", result);
96 }
97 return results.getMappedResults();
98 }
99
100 /**
101 * 使用管道操作符 $group 结合表达式操作符 $avg 进行聚合统计
102 *
103 * @return 聚合结果
104 */
105 public Object aggregationGroupAvg() {
106 // 使用管道操作符 $group 进行分组,然后统计各个组文档某字段值平均值
107 AggregationOperation group = Aggregation.group("sex").avg("salary").as("salaryAvg");
108 // 将操作加入到聚合对象中
109 Aggregation aggregation = Aggregation.newAggregation(group);
110 // 执行聚合查询
111 AggregationResults<Map> results = mongoTemplate.aggregate(aggregation, COLLECTION_NAME, Map.class);
112 for (Map result : results.getMappedResults()) {
113 log.info("{}", result);
114 }
115 return results.getMappedResults();
116 }
117
118 /**
119 * 使用管道操作符 $group 结合表达式操作符 $first 获取每个组的包含某字段的文档的第一条数据
120 *
121 * @return 聚合结果
122 */
123 public Object aggregationGroupFirst() {
124 // 先对数据进行排序,然后使用管道操作符 $group 进行分组,最后统计各个组文档某字段值第一个值
125 AggregationOperation sort = Aggregation.sort(Sort.by("salary").ascending());
126 AggregationOperation group = Aggregation.group("sex").first("salary").as("salaryFirst");
127 // 将操作加入到聚合对象中
128 Aggregation aggregation = Aggregation.newAggregation(sort, group);
129 // 执行聚合查询
130 AggregationResults<Map> results = mongoTemplate.aggregate(aggregation, COLLECTION_NAME, Map.class);
131 for (Map result : results.getMappedResults()) {
132 log.info("{}", result);
133 }
134 return results.getMappedResults();
135 }
136
137 /**
138 * 使用管道操作符 $group 结合表达式操作符 $last 获取每个组的包含某字段的文档的最后一条数据
139 *
140 * @return 聚合结果
141 */
142 public Object aggregationGroupLast() {
143 // 先对数据进行排序,然后使用管道操作符 $group 进行分组,最后统计各个组文档某字段值第最后一个值
144 AggregationOperation sort = Aggregation.sort(Sort.by("salary").ascending());
145 AggregationOperation group = Aggregation.group("sex").last("salary").as("salaryLast");
146 // 将操作加入到聚合对象中
147 Aggregation aggregation = Aggregation.newAggregation(sort, group);
148 // 执行聚合查询
149 AggregationResults<Map> results = mongoTemplate.aggregate(aggregation, COLLECTION_NAME, Map.class);
150 for (Map result : results.getMappedResults()) {
151 log.info("{}", result);
152 }
153 return results.getMappedResults();
154 }
155
156 /**
157 * 使用管道操作符 $group 结合表达式操作符 $push 获取某字段列表
158 *
159 * @return 聚合结果
160 */
161 public Object aggregationGroupPush() {
162 // 先对数据进行排序,然后使用管道操作符 $group 进行分组,然后以数组形式列出某字段的全部值
163 AggregationOperation push = Aggregation.group("sex").push("salary").as("salaryFirst");
164 // 将操作加入到聚合对象中
165 Aggregation aggregation = Aggregation.newAggregation(push);
166 // 执行聚合查询
167 AggregationResults<Map> results = mongoTemplate.aggregate(aggregation, COLLECTION_NAME, Map.class);
168 for (Map result : results.getMappedResults()) {
169 log.info("{}", result);
170 }
171 return results.getMappedResults();
172 }
173
174}
(2)、聚合管道操作符
1import lombok.extern.slf4j.Slf4j;
2import org.springframework.data.domain.Sort;
3import org.springframework.data.mongodb.core.MongoTemplate;
4import org.springframework.data.mongodb.core.aggregation.Aggregation;
5import org.springframework.data.mongodb.core.aggregation.AggregationOperation;
6import org.springframework.data.mongodb.core.aggregation.AggregationResults;
7import org.springframework.data.mongodb.core.query.Criteria;
8import org.springframework.stereotype.Service;
9import javax.annotation.Resource;
10import java.util.Map;
11
12@Slf4j
13@Service
14public class AggregatePipelineService {
15
16 /**
17 * 设置集合名称
18 */
19 private static final String COLLECTION_NAME = "users";
20
21 @Resource
22 private MongoTemplate mongoTemplate;
23
24 /**
25 * 使用 $group 和 $match 聚合,先使用 $match 过滤文档,然后再使用 $group 进行分组
26 *
27 * @return 聚合结果
28 */
29 public Object aggregateGroupMatch() {
30 // 设置聚合条件,先使用 $match 过滤岁数大于 25 的用户,然后按性别分组,统计每组用户工资最高值
31 AggregationOperation match = Aggregation.match(Criteria.where("age").lt(25));
32 AggregationOperation group = Aggregation.group("sex").max("salary").as("sexSalary");
33 // 将操作加入到聚合对象中
34 Aggregation aggregation = Aggregation.newAggregation(match, group);
35 // 执行聚合查询
36 AggregationResults<Map> results = mongoTemplate.aggregate(aggregation, COLLECTION_NAME, Map.class);
37 for (Map result : results.getMappedResults()) {
38 log.info("{}", result);
39 }
40 return results.getMappedResults();
41 }
42
43 /**
44 * 使用 $group 和 $sort 聚合,先使用 $group 进行分组,然后再使用 $sort 排序
45 *
46 * @return 聚合结果
47 */
48 public Object aggregateGroupSort() {
49 // 设置聚合条件,按岁数分组,然后统计每组用户工资最大值和用户数,按每组用户工资最大值升序排序
50 AggregationOperation group = Aggregation.group("age")
51 .max("salary").as("ageSalary")
52 .count().as("ageCount");
53 AggregationOperation sort = Aggregation.sort(Sort.by("ageSalary").ascending());
54 // 将操作加入到聚合对象中
55 Aggregation aggregation = Aggregation.newAggregation(group, sort);
56 // 执行聚合查询
57 AggregationResults<Map> results = mongoTemplate.aggregate(aggregation, COLLECTION_NAME, Map.class);
58 for (Map result : results.getMappedResults()) {
59 log.info("{}", result);
60 }
61 return results.getMappedResults();
62 }
63
64 /**
65 * 使用 $group 和 $limit 聚合,先使用 $group 进行分组,然后再使用 $limit 限制一定数目文档
66 *
67 * @return 聚合结果
68 */
69 public Object aggregateGroupLimit() {
70 // 设置聚合条件,先按岁数分组,然后求每组用户的工资总数、最大值、最小值、平均值,限制只能显示五条
71 AggregationOperation group = Aggregation.group("age")
72 .sum("salary").as("sumSalary")
73 .max("salary").as("maxSalary")
74 .min("salary").as("minSalary")
75 .avg("salary").as("avgSalary");
76 AggregationOperation limit = Aggregation.limit(5L);
77 // 将操作加入到聚合对象中
78 Aggregation aggregation = Aggregation.newAggregation(group, limit);
79 // 执行聚合查询
80 AggregationResults<Map> results = mongoTemplate.aggregate(aggregation, COLLECTION_NAME, Map.class);
81 for (Map result : results.getMappedResults()) {
82 log.info("{}", result);
83 }
84 return results.getMappedResults();
85 }
86
87 /**
88 * 使用 $group 和 $skip 聚合,先使用 $group 进行分组,然后再使用 $skip 跳过一定数目文档
89 *
90 * @return 聚合结果
91 */
92 public Object aggregateGroupSkip() {
93 // 设置聚合条件,先按岁数分组,然后求每组用户的工资总数、最大值、最小值、平均值,跳过前 2 条
94 AggregationOperation group = Aggregation.group("age")
95 .sum("salary").as("sumSalary")
96 .max("salary").as("maxSalary")
97 .min("salary").as("minSalary")
98 .avg("salary").as("avgSalary");
99 AggregationOperation limit = Aggregation.skip(2L);
100 // 将操作加入到聚合对象中
101 Aggregation aggregation = Aggregation.newAggregation(group, limit);
102 // 执行聚合查询
103 AggregationResults<Map> results = mongoTemplate.aggregate(aggregation, COLLECTION_NAME, Map.class);
104 for (Map result : results.getMappedResults()) {
105 log.info("{}", result);
106 }
107 return results.getMappedResults();
108 }
109
110 /**
111 * 使用 $group 和 $project 聚合,先使用 $group 进行分组,然后再使用 $project 限制显示的字段
112 *
113 * @return 聚合结果
114 */
115 public Object aggregateGroupProject() {
116 // 设置聚合条件,按岁数分组,然后求每组用户工资最大值、最小值,然后使用 $project 限制值显示 salaryMax 字段
117 AggregationOperation group = Aggregation.group("age")
118 .max("salary").as("maxSalary")
119 .min("salary").as("minSalary");
120 AggregationOperation project = Aggregation.project("maxSalary");
121 // 将操作加入到聚合对象中
122 Aggregation aggregation = Aggregation.newAggregation(group, project);
123 // 执行聚合查询
124 AggregationResults<Map> results = mongoTemplate.aggregate(aggregation, COLLECTION_NAME, Map.class);
125 for (Map result : results.getMappedResults()) {
126 log.info("{}", result);
127 }
128 return results.getMappedResults();
129 }
130
131 /**
132 * 使用 $group 和 $unwind 聚合,先使用 $project 进行分组,然后再使用 $unwind 拆分文档中的数组为一条新文档记录
133 *
134 * @return 聚合结果
135 */
136 public Object aggregateProjectUnwind() {
137 // 设置聚合条件,设置显示`name`、`age`、`title`字段,然后将结果中的多条文档按 title 字段进行拆分
138 AggregationOperation project = Aggregation.project("name", "age", "title");
139 AggregationOperation unwind = Aggregation.unwind("title");
140 // 将操作加入到聚合对象中
141 Aggregation aggregation = Aggregation.newAggregation(project, unwind);
142 // 执行聚合查询
143 AggregationResults<Map> results = mongoTemplate.aggregate(aggregation, COLLECTION_NAME, Map.class);
144 for (Map result : results.getMappedResults()) {
145 log.info("{}", result);
146 }
147 return results.getMappedResults();
148 }
149
150}
聚合管道操作符:
- $project: 可以从文档中选择想要的字段,和不想要的字段(指定的字段可以是来自输入文档或新计算字段的现有字段 ,也可以通过管道表达式进行一些复杂的操作,例如数学操作,日期操作,字符串操作,逻辑操作。
- $match: 用于过滤数据,只输出符合条件的文档。$match使用MongoDB的标准查询操作。
- $limit: 用来限制MongoDB聚合管道返回的文档数。
- $skip: 在聚合管道中跳过指定数量的文档,并返回余下的文档。
- $unwind: 将文档中的某一个数组类型字段拆分成多条,每条包含数组中的一个值。
- $group: 将集合中的文档分组,可用于统计结果。
- $sort: 将输入文档排序后输出。
9、MongoDB 索引操作
(1)、创建索引
1import com.mongodb.client.model.Filters;
2import com.mongodb.client.model.IndexOptions;
3import com.mongodb.client.model.Indexes;
4import lombok.extern.slf4j.Slf4j;
5import org.springframework.data.mongodb.core.MongoTemplate;
6import org.springframework.stereotype.Service;
7import javax.annotation.Resource;
8
9@Slf4j
10@Service
11public class CreateIndexService {
12
13 /** 设置集合名称 */
14 private static final String COLLECTION_NAME = "users";
15
16 @Resource
17 private MongoTemplate mongoTemplate;
18
19 /**
20 * 创建升序索引
21 *
22 * @return 索引信息
23 */
24 public Object createAscendingIndex() {
25 // 设置字段名称
26 String field = "name";
27 // 创建索引
28 return mongoTemplate.getCollection(COLLECTION_NAME).createIndex(Indexes.ascending(field));
29 }
30
31 /**
32 * 创建降序索引
33 *
34 * @return 索引信息
35 */
36 public Object createDescendingIndex() {
37 // 设置字段名称
38 String field = "name";
39 // 创建索引
40 return mongoTemplate.getCollection(COLLECTION_NAME).createIndex(Indexes.descending(field));
41 }
42
43 /**
44 * 创建升序复合索引
45 *
46 * @return 索引信息
47 */
48 public Object createCompositeIndex() {
49 // 设置字段名称
50 String field1 = "name";
51 String field2 = "age";
52 // 创建索引
53 return mongoTemplate.getCollection(COLLECTION_NAME).createIndex(Indexes.ascending(field1, field2));
54 }
55
56 /**
57 * 创建文字索引
58 *
59 * @return 索引信息
60 */
61 public Object createTextIndex() {
62 // 设置字段名称
63 String field = "name";
64 // 创建索引
65 return mongoTemplate.getCollection(COLLECTION_NAME).createIndex(Indexes.text(field));
66 }
67
68 /**
69 * 创建哈希索引
70 *
71 * @return 索引信息
72 */
73 public Object createHashIndex() {
74 // 设置字段名称
75 String field = "name";
76 // 创建索引
77 return mongoTemplate.getCollection(COLLECTION_NAME).createIndex(Indexes.hashed(field));
78 }
79
80 /**
81 * 创建升序唯一索引
82 *
83 * @return 索引信息
84 */
85 public Object createUniqueIndex() {
86 // 设置字段名称
87 String indexName = "name";
88 // 配置索引选项
89 IndexOptions options = new IndexOptions();
90 // 设置为唯一索引
91 options.unique(true);
92 // 创建索引
93 return mongoTemplate.getCollection(COLLECTION_NAME).createIndex(Indexes.ascending(indexName), options);
94 }
95
96 /**
97 * 创建局部索引
98 *
99 * @return 索引信息
100 */
101 public Object createPartialIndex() {
102 // 设置字段名称
103 String field = "name";
104 // 配置索引选项
105 IndexOptions options = new IndexOptions();
106 // 设置过滤条件
107 options.partialFilterExpression(Filters.exists("name", true));
108 // 创建索引
109 return mongoTemplate.getCollection(COLLECTION_NAME).createIndex(Indexes.ascending(field), options);
110 }
111
112}
(2)、查询索引
1import com.mongodb.client.ListIndexesIterable;
2import lombok.extern.slf4j.Slf4j;
3import org.bson.Document;
4import org.springframework.data.mongodb.core.MongoTemplate;
5import org.springframework.stereotype.Service;
6import javax.annotation.Resource;
7import java.util.ArrayList;
8import java.util.List;
9
10/**
11 * 查询索引操作
12 *
13 * @author mydlq
14 */
15@Slf4j
16@Service
17public class QueryIndexService {
18
19 /** 设置集合名称 */
20 private static final String COLLECTION_NAME = "users";
21
22 @Resource
23 private MongoTemplate mongoTemplate;
24
25 /**
26 * 获取当前【集合】对应的【所有索引】的【名称列表】
27 *
28 * @return 当前【集合】所有【索引名称列表】
29 */
30 public Object getIndexAll() {
31 // 获取集合中所有列表
32 ListIndexesIterable<Document> indexList = mongoTemplate.getCollection(COLLECTION_NAME).listIndexes();
33 // 创建字符串集合
34 List<Document> list = new ArrayList<>();
35 // 获取集合中全部索引信息
36 for (Document document : indexList) {
37 log.info("索引列表:{}",document);
38 list.add(document);
39 }
40 return list;
41 }
42
43}
(3)、删除索引
1import lombok.extern.slf4j.Slf4j;
2import org.springframework.data.mongodb.core.MongoTemplate;
3import org.springframework.stereotype.Service;
4import javax.annotation.Resource;
5
6@Slf4j
7@Service
8public class RemoveIndexService {
9
10 @Resource
11 private MongoTemplate mongoTemplate;
12
13 /** 设置集合名称 */
14 private static final String COLLECTION_NAME = "users";
15
16 /**
17 * 根据索引名称移除索引
18 */
19 public void removeIndex() {
20 // 设置索引名称
21 String indexName = "name_1";
22 // 删除集合中某个索引
23 mongoTemplate.getCollection(COLLECTION_NAME).dropIndex(indexName);
24 }
25
26 /**
27 * 移除全部索引
28 */
29 public void removeIndexAll() {
30 // 删除集合中全部索引
31 mongoTemplate.getCollection(COLLECTION_NAME).dropIndexes();
32 }
33
34}
10、MongoDB RunCommand 命令操作
(1)、RunCommand 命令
1import org.bson.Document;
2import org.bson.conversions.Bson;
3import org.springframework.data.mongodb.core.MongoTemplate;
4import org.springframework.stereotype.Service;
5import javax.annotation.Resource;
6
7@Service
8public class RunCommandService {
9
10 @Resource
11 private MongoTemplate mongoTemplate;
12
13 /**
14 * 执行 mongoDB 自定义命令,详情可以查看:https://docs.mongodb.com/manual/reference/command/
15 *
16 * @return 执行命令返回结果的 Json 结果
17 * @description 执行自定义 mongoDB 命令
18 */
19 public Object runCommand() {
20 // 自定义命令
21 String jsonCommand = "{\"buildInfo\":1}";
22 // 将 JSON 字符串解析成 MongoDB 命令
23 Bson bson = Document.parse(jsonCommand);
24 // 执行自定义命令
25 return mongoTemplate.getDb().runCommand(bson);
26 }
27
28}
五、SpringBoot 引入 MongoDB 中的事务
注意:单节点 mongodb 不支持事务,需要搭建 MongoDB 复制集。
1、配置事务管理器
1import org.springframework.context.annotation.Bean;
2import org.springframework.context.annotation.Configuration;
3import org.springframework.data.mongodb.MongoDatabaseFactory;
4import org.springframework.data.mongodb.MongoTransactionManager;
5
6/**
7 * 配置事务管理器
8 *
9 * @author mydlq
10 */
11@Configuration
12public class TransactionConfig {
13
14 @Bean
15 MongoTransactionManager transactionManager(MongoDatabaseFactory dbFactory) {
16 return new MongoTransactionManager(dbFactory);
17 }
18
19}
2、创建事务测试服务
1import mydlq.club.example.entity.Status;
2import mydlq.club.example.entity.User;
3import org.springframework.data.mongodb.core.MongoTemplate;
4import org.springframework.stereotype.Service;
5import org.springframework.transaction.annotation.Transactional;
6import javax.annotation.Resource;
7import java.util.Date;
8
9@Service
10public class TransactionExample {
11
12 /** 设置集合名称 */
13 private static final String COLLECTION_NAME = "users";
14
15 @Resource
16 private MongoTemplate mongoTemplate;
17
18 @Transactional(rollbackFor = Exception.class)
19 public Object transactionTest(){
20 // 设置两个用户信息
21 User user1 = new User()
22 .setId("11")
23 .setAge(22)
24 .setSex("男")
25 .setRemake("无")
26 .setSalary(1500)
27 .setName("shiyi")
28 .setBirthday(new Date())
29 .setStatus(new Status().setHeight(180).setWeight(150));
30 // 插入数据
31 User newUser1 = mongoTemplate.insert(user1, COLLECTION_NAME);
32 // 抛出异常,观察数据是否进行回滚
33 int error = 1/0;
34 return newUser1;
35 }
36
37}
如果对你有帮助,别忘了点颗星嘞~
---END---
!版权声明:本博客内容均为原创,每篇博文作为知识积累,写博不易,转载请注明出处。