SpringBoot-MongoDB入门教程

概述

本篇是mongodb入门教程。

实战

pom依赖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.0.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>cn.idea360</groupId>
<artifactId>idc-mongo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>idc-mongo</name>
<description>Demo project for Spring Boot</description>

<properties>
<java.version>1.8</java.version>
</properties>

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.68</version>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>

</project>

application.properties

1
spring.data.mongodb.uri=mongodb://root:root@localhost:27017/kcall

创建实体类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/**
* @author 当我遇上你
* @公众号 当我遇上你
* @since 2020-06-08
*/
@Data
@ToString
public class User implements Serializable {
private int id;
private String userName;
private String password;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime createTime;

public User(int id, String userName, String password) {
this.id = id;
this.userName = userName;
this.password = password;
this.createTime = LocalDateTime.now();
}
}

配置不存储_class

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/**
* 不保存_class到mongo中
* @author 当我遇上你
* @公众号 当我遇上你
* @since 2020-06-08
*/
@Configuration
public class MongoConfig {
@Bean
public MappingMongoConverter mappingMongoConverter(MongoDatabaseFactory factory, MongoMappingContext context, BeanFactory beanFactory) {
DbRefResolver dbRefResolver = new DefaultDbRefResolver(factory);
MappingMongoConverter mappingConverter = new MappingMongoConverter(dbRefResolver, context);
try {
mappingConverter.setCustomConversions(beanFactory.getBean(CustomConversions.class));
} catch (NoSuchBeanDefinitionException ignore) {
}

// Don't save _class to mongo
mappingConverter.setTypeMapper(new DefaultMongoTypeMapper(null));

return mappingConverter;
}
}

基本操作

  1. MongoTemplate
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
package com.example.demo;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.example.demo.model.AiUser;
import com.example.demo.model.Project;
import com.example.demo.model.User;
import com.mongodb.BasicDBObject;
import com.mongodb.bulk.BulkWriteResult;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.BulkOperations;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.aggregation.Aggregation;
import org.springframework.data.mongodb.core.aggregation.AggregationResults;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.data.repository.support.PageableExecutionUtils;
import org.springframework.data.util.Pair;
import org.springframework.util.StringUtils;

import java.util.*;

/**
* @author 当我遇上你
* @公众号 当我遇上你
* @since 2020-06-08
*/
@Slf4j
@SpringBootTest
public class UserTest {

@Autowired
private MongoTemplate mongoTemplate;

/**
* 1. 插入数据
* 2. 表名大小写敏感
* 3. id不用数据库自带的uuid,换为自定义自增主键
* 4. 不保存_class到mongo中
* User(id=100, userName=name100, password=123, createTime=2020-07-23T11:31:14.567044)
*/
@Test
public void add1() {
User user = new User(100, "name100", "123");
User save = mongoTemplate.save(user, "user");
log.info(save.toString());
}

/**
* 主键相同会覆盖数据
* User(id=100, userName=name100, password=123, createTime=2021-04-29T22:21:15.694248)
*/
@Test
public void add2() {
User user = new User(100, "name100", "123");
User save = mongoTemplate.save(user, "user");
log.info(save.toString());
}

/**
* 批量插入
* id存在会抛出异常: DuplicateKeyException
*/
@Test
public void add3() {
List<User> list = new ArrayList<>();
for (int i = 1; i <= 10; i++) {
User user = new User(i, "name" + i, "123");
list.add(user);
}
Collection<User> users = mongoTemplate.insertAll(list);
log.info(users.toString());
}

/**
* 批量插入
* id存在会抛出异常: DuplicateKeyException
*/
@Test
public void add4() {
List<User> list = new ArrayList<>();
for (int i = 1; i <= 10; i++) {
User user = new User(i, "name" + i, "123");
list.add(user);
}
Collection<User> users = mongoTemplate.insert(list, "user");
log.info(users.toString());
}


/**
* User(id=1, userName=name1, password=123, createTime=2020-07-23T11:32:04.550)
*/
@Test
public void query1() {
Query query = new Query(Criteria.where("_id").is(1));
// 模糊查询
query.addCriteria(Criteria.where("userName").regex("name"));
User user = mongoTemplate.findOne(query, User.class, "user");
log.info(user.toString());
}

/**
* User(id=1, userName=name1, password=123, createTime=2020-07-23T11:32:04.550)
*/
@Test
public void query2() {
Query query = Query.query(Criteria.where("_id").is(1));
User user = mongoTemplate.findOne(query, User.class, "user");
log.info(user.toString());
}

/**
* [User(id=1, userName=name1, password=123, createTime=2020-07-23T11:32:04.550), User(id=2, userName=name2, password=123, createTime=2020-07-23T11:32:04.550), User(id=3, userName=name3, password=123, createTime=2020-07-23T11:32:04.550)]
*/
@Test
public void in() {
Query query = Query.query(Criteria.where("_id").in(1, 2, 3));
List<User> list = mongoTemplate.find(query, User.class, "user");
log.info(list.toString());
}

/**
* 分页查询
* {"content":[{"createTime":"2020-07-23T11:32:04.550","id":6,"password":"123","userName":"name6"},{"createTime":"2020-07-23T11:32:04.550","id":7,"password":"123","userName":"name7"},{"createTime":"2020-07-23T11:32:04.550","id":8,"password":"123","userName":"name8"},{"createTime":"2020-07-23T11:32:04.550","id":9,"password":"123","userName":"name9"},{"createTime":"2020-07-23T11:32:04.550","id":10,"password":"123","userName":"name10"}],"empty":false,"first":false,"last":false,"number":1,"numberOfElements":5,"pageable":{"offset":5,"pageNumber":1,"pageSize":5,"paged":true,"sort":{"empty":true,"sorted":false,"unsorted":true},"unpaged":false},"size":5,"sort":{"$ref":"$.pageable.sort"},"totalElements":11,"totalPages":3}
*/
@Test
public void page() {
PageRequest pageRequest = PageRequest.of(1, 5);
Query query = Query.query(Criteria.where("password").is("123"))
.with(Sort.by(Sort.Direction.ASC, "_id"));
// 查询总数
int count = (int) mongoTemplate.count(query, User.class, "user");
// 加入分页条件
query.with(pageRequest);
List<User> users = mongoTemplate.find(query, User.class, "user");
// 分页
Page<User> page = PageableExecutionUtils.getPage(users, pageRequest, () -> count);
log.info(JSONObject.toJSONString(page));
}

/**
* 时间段查询(注意时区)
*/
@Test
public void time() {

String startTime = "2021-04-20 14:14:20";
String endTime = "2021-04-30 14:15:41";

PageRequest pageRequest = PageRequest.of(1, 5);
Query query = Query.query(Criteria.where("password").is("123"))
.with(Sort.by(Sort.Direction.ASC, "_id"));

// 时间段查询
if (!StringUtils.isEmpty(startTime) && !StringUtils.isEmpty(endTime)) {
Criteria criteria = new Criteria();
criteria.andOperator(Criteria.where("createTime").gte(startTime), Criteria.where("createTime").lt(endTime));
query.addCriteria(criteria);
} else if (!Objects.isNull(startTime)) {
query.addCriteria(Criteria.where("createTime").gte(startTime));
} else if (!Objects.isNull(endTime)) {
query.addCriteria(Criteria.where("createTime").lt(endTime));
}

// 查询总数
int count = (int) mongoTemplate.count(query, User.class, "user");
// 加入分页条件
query.with(pageRequest);
List<User> users = mongoTemplate.find(query, User.class, "user");
// 分页
Page<User> page = PageableExecutionUtils.getPage(users, pageRequest, () -> count);
log.info(JSONObject.toJSONString(page));
}

/**
* 如果查询字段中有list, 业务需要匹配子对象中的字段。
*
* 示例实体:
* @Data
* public class AiUser {
* private long id;
* private List<Project> projects;
* }
*
* @Data
* public class Project {
* private String name;
* }
*
* 则 mongoTemplate 查询如下所示: [{"id":1,"projects":[{"name":"项目"}]}]
*/
@Test
public void queryChild() {
Project project = new Project();
project.setName("项目");

AiUser aiUser = new AiUser();
aiUser.setId(1);
aiUser.setProjects(Collections.singletonList(project));
// 保存嵌套数据
mongoTemplate.save(aiUser, "ai_user");

// 根据子集合中的数据查询
List<AiUser> aiUsers = mongoTemplate.find(Query.query(Criteria.where("projects.name").is("项目")), AiUser.class, "ai_user");
log.info(JSONArray.toJSONString(aiUsers));
}


/**
* 批量查询
* [{"createTime":"2021-04-29T22:51:27.636","id":1,"password":"123","userName":"name1"},{"createTime":"2021-04-29T22:51:27.636","id":3,"password":"123","userName":"name3"},{"createTime":"2021-04-29T22:51:27.636","id":5,"password":"123","userName":"name5"}]
*/
@Test
public void queryBatch() {
List<String> nameQuery = Arrays.asList("name1", "name3", "name5");
Query query = new Query();
Criteria criteria = new Criteria();
Criteria[] cs = new Criteria[nameQuery.size()];

for(int i=0; i<nameQuery.size(); i++){
cs[i] = Criteria.where("userName").is(nameQuery.get(i));
}
criteria.orOperator(cs);
query.addCriteria(criteria);
List<User> users = mongoTemplate.find(query, User.class, "user");
log.info(JSONArray.toJSONString(users));
}

/**
* 更新(save操作底层会调用upsert)
* upsert操作会先在集合中进行数据查找,如果数据已经存在,则更新,否则才插入
*/
@Test
public void update() {
Query query = new Query(Criteria.where("_id").is(100));
Update update = new Update();
update.set("userName", "admin");
mongoTemplate.upsert(query, update, "user");
}

/**
* 批量更新
* {"deletedCount":0,"insertedCount":0,"inserts":[],"matchedCount":3,"modifiedCount":3,"upserts":[]}
*/
@Test
public void update2() {
List<Integer> ids = Arrays.asList(1, 2, 3);
List<Pair<Query, Update>> updateList = new ArrayList<>(3);
BulkOperations operations = mongoTemplate.bulkOps(BulkOperations.BulkMode.UNORDERED, "user");
ids.forEach(id -> {
Query query = new Query(new Criteria("_id").is(id));
Update update = new Update();
update.set("userName", "batch-update-" + id);
Pair<Query, Update> updatePair = Pair.of(query, update);
updateList.add(updatePair);
});
operations.upsert(updateList);
BulkWriteResult execute = operations.execute();
log.info("{}", JSONObject.toJSONString(execute));
}

/**
* 删除
*/
@Test
public void delete() {
Query query = new Query(Criteria.where("_id").in(100));
mongoTemplate.findAllAndRemove(query, User.class, "user");
}
/**
* 2021-04-29 22:51:48.436 INFO 97804 --- [ main] com.example.demo.UserTest : 聚合: [{"_id":"name1","sum":1}]
* 2021-04-29 22:51:48.438 INFO 97804 --- [ main] com.example.demo.UserTest : 聚合: [{"_id":"name10","sum":1}]
* 2021-04-29 22:51:48.438 INFO 97804 --- [ main] com.example.demo.UserTest : 聚合: [{"_id":"name100","sum":1}]
*/
@Test
public void aggregation() {
// 将操作加入到聚合对象中
Aggregation aggregation = Aggregation.newAggregation(
// 条件匹配
Aggregation.match(Criteria.where("userName").regex("name1")),
// 使用管道操作符 $group 进行分组,然后统计各个组的文档数量
Aggregation.group("userName").count().as("sum"),
// 排序
Aggregation.sort(Sort.by("_id").ascending())
);
// 执行聚合查询
AggregationResults<BasicDBObject> results = mongoTemplate.aggregate(aggregation, "user", BasicDBObject.class);

for (Iterator<BasicDBObject> iterator = results.iterator(); iterator.hasNext(); ) {
BasicDBObject obj = iterator.next();
log.info("聚合: [{}]", JSONObject.toJSONString(obj));
}
}

}
  1. 像 JPA 一样操作
1
2
3
public interface CustomerRepository extends MongoRepository<R, String> {

}

最后

本文到此结束,感谢阅读。如果您觉得不错,请关注公众号【当我遇上你】,您的支持是我写作的最大动力。

参考