MongoDB JAVA 新增+查询
上接 SpringBoot 整合 MongoDB,记一下 MongoDB 的 CRUD 方法。
Create 新增
使用 MongoRepository
方式的新增非常简单,之前的整合中已经尝试过,这里再总结一下:
首先需要有对应的实体类对象:
@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class User {
@Id
private String userId;
private String name;
private Integer age;
private Date createDate;
}
然后创建这个实体类对应的仓库类,继承 MongoRepository
接口,泛型为实体类和实体类的ID类型:
public interface UserRepository extends MongoRepository<User, String> {
// 无需实现
}
最后直接调用 UserRepository
的 save 方法就可以实现新增操作:
@RequestMapping("/createUser")
public User createUser(){
User user = new User("0723","Qiyuan",21, new Date());
User saveUser = userRepository.save(user);
System.out.println(saveUser);
return saveUser;
}
访问这个请求地址,会返回这个 User 的信息,说明新增数据成功:
{"userId":"0723","name":"Qiyuan","age":21,"createDate":"2023-05-06T02:46:28.598+00:00"}
如果是批量新增,则对应的将对象放入 List 中即可:
@RequestMapping("/createUserList")
public List<User> createUserList(){
// 将新增的对象放入 List
List<User> userList = new ArrayList<>();
userList.add(new User("0718","Irror",18, new Date()));
userList.add(new User("0123","Inory",19, new Date()));
List<User> saveUserList = userRepository.saveAll(userList);
System.out.println(saveUserList);
return saveUserList;
}
访问这个请求地址,会以 List 的形式返回增加的 User 的信息,说明增加成功:
[{"userId":"0718","name":"Irror","age":18,"createDate":"2023-05-06T02:48:14.460+00:00"},
{"userId":"0123","name":"Inory","age":19,"createDate":"2023-05-06T02:48:14.460+00:00"}]
查看数据库中的数据,与增加的数据也一致(ID 0118 的是以前加的)。
Read 查询
MongoDB 的查询方式有很多种,这里都试一下吧。
仓库类
MongoRepository
提供了许多增删改查的方法,查询的方法即 findAll()
,之前已经使用过,但这个方法除了直接查询所有,通过不同的参数还支持排序、分页、条件查询,对应了 findAll()
方法的四个重载。
先看直接使用,调用 findAll()
可以获取集合中的所有对象:
@RequestMapping("/getAllUsers")
public List<User> getAllUsers() {
return userRepository.findAll();
}
请求这个接口,返回对象列表:
[{"userId":"0118","name":"qiyuanc","age":20,"createDate":"2023-04-14T15:13:00.000+00:00"},
{"userId":"0723","name":"Qiyuan","age":21,"createDate":"2023-05-06T02:46:28.598+00:00"},
{"userId":"0718","name":"Irror","age":18,"createDate":"2023-05-06T02:48:14.460+00:00"},
{"userId":"0123","name":"Inory","age":19,"createDate":"2023-05-06T02:48:14.460+00:00"}]
通过构造一个排序 Sort 对象并传入,可以实现排序查询:
@RequestMapping("/getUsersBySort")
public List<User> getUsersBySort() {
// Sort.Direction.ASC 升序 DESC 降序
Sort sort = Sort.by(Sort.Direction.ASC, "age");
// 根据传入的排序条件查询
List<User> users = userRepository.findAll(sort);
return userRepository.findAll();
}
请求这个接口,返回的结果就是按年龄升序排列的了:
[{"userId":"0718","name":"Irror","age":18,"createDate":"2023-05-06T02:48:14.460+00:00"},
{"userId":"0123","name":"Inory","age":19,"createDate":"2023-05-06T02:48:14.460+00:00"},
{"userId":"0118","name":"qiyuanc","age":20,"createDate":"2023-04-14T15:13:00.000+00:00"},
{"userId":"0723","name":"Qiyuan","age":21,"createDate":"2023-05-06T02:46:28.598+00:00"}]
通过构造一个分页 PageRequest 对象并传入,可以实现分页查询,需要注意,MongoDB 的页数从0开始:
@RequestMapping("/getUsersByPage/{page}/{rows}")
public Page<User> getUsersByPage(@PathVariable int page, @PathVariable int rows) {
// 构造方法访问权限为 protected
// MongoDB 页数从0开始 需要 -1
PageRequest pageRequest = PageRequest.of(page-1, rows);
return userRepository.findAll(pageRequest);
}
请求 /getUsersByPage/1/2
返回的就是包含第一页的两条数据的分页对象:
{"content":
[{"userId":"0118","name":"qiyuanc","age":20,"createDate":"2023-04-14T15:13:00.000+00:00"},
{"userId":"0723","name":"Qiyuan","age":21,"createDate":"2023-05-06T02:46:28.598+00:00"}],
"pageable":
{"sort":{"sorted":false,"unsorted":true,"empty":true},"offset":0,"pageNumber":0,"pageSize":2,"unpaged":false,"paged":true},
"totalPages":2,"totalElements":4,"last":false,"number":0,"size":2,
"sort":{"sorted":false,"unsorted":true,"empty":true},
"numberOfElements":2,"first":true,"empty":false}
最后是条件查询,需要构建模板 Example 对象,在构建这个对象前又需要一个匹配器指定匹配规则、一个实体对象存放匹配参数,还是挺麻烦的,网上能搜到的内容也少,可能就不怎么常用:
@RequestMapping("/getUsersByExample")
public List<User> getUsersByExample() {
// 匹配规则:忽略大小写 + name 包含
ExampleMatcher matcher = ExampleMatcher.matching()
.withIgnoreCase()
.withMatcher("name", ExampleMatcher.GenericPropertyMatchers.contains());
User user = new User();
user.setName("qiyuan");
// 查询模板
Example<User> example = Example.of(user, matcher);
List<User> userList = userRepository.findAll(example);
return userList;
}
请求这个接口就返回了条件查询的结果,名字包含 qiyuan
的对象:
[{"userId":"0118","name":"qiyuanc","age":20,"createDate":"2023-04-14T15:13:00.000+00:00"},
{"userId":"0723","name":"Qiyuan","age":21,"createDate":"2023-05-06T02:46:28.598+00:00"}]
仓库类的查询方式大概就这么多,虽然可以直接用,但条件查询好像不是很友好啊。。。
@Qurey注解
上面是直接使用仓库类自带的方法进行查询,在简单场景下应该是够用,但复杂一点的场景就会麻烦。所以 MongoDB 支持使用 @Query
注解自定义查询方法,使用的也是 MongoDB 的原生查询语句。
在仓库类 UserRepository
中添加两个方法,一个是上面实现了的根据名字查询(忽略大小写)的方法,还有一个是查询年龄小于输入参数的方法:
public interface UserRepository extends MongoRepository<User, String> {
// 自定义查询方法
@Query("{ 'name' : { $regex: ?0, $options: 'i' } }")
List<User> findByNameContainingIgnoreCase(String name);
@Query("{ 'age' : { $lt: ?0 } }")
List<User> findByAgeLessThan(int age);
}
这两个方法都通过 @Query
注解自定义了查询逻辑,这里使用了 $regex
来进行模糊匹配,$options
选项设置为 'i'
表示不区分大小写,$lt
即 LessThan,?0
则代表了第一个参数。
使用时直接调用,传入相应的参数即可:
@RequestMapping("/getUserByName/{name}")
public List<User> getUserByName(@PathVariable String name){
// 调用仓库类的方法
List<User> saveUserList = userRepository.findByNameContainingIgnoreCase(name);
return saveUserList;
}
@RequestMapping("/getUserByLessThanAge/{age}")
public List<User> getUserByLessThanAge(@PathVariable int age){
// 调用仓库类的方法
List<User> saveUserList = userRepository.findByAgeLessThan(age);
return saveUserList;
}
为了方便我都使用了路径参数,请求 /getUserByName/qiyuan
会返回名字包含 qiyuan 的用户
[{"userId":"0118","name":"qiyuanc","age":20,"createDate":"2023-04-14T15:13:00.000+00:00"},
{"userId":"0723","name":"Qiyuan","age":21,"createDate":"2023-05-06T02:46:28.598+00:00"}]
请求 /getUserByLessThanAge/20
会返回年龄小于20的用户:
[{"userId":"0718","name":"Irror","age":18,"createDate":"2023-05-06T02:48:14.460+00:00"},
{"userId":"0123","name":"Inory","age":19,"createDate":"2023-05-06T02:48:14.460+00:00"}]
这种方式通过自己写查询语句,比仓库类自带的方法灵活多了,但也相对复杂一定,有舍有得。
Query对象
除了使用 @Query
预先定义查询方法外,也可以通过创建 Query
对象并设置其中的 Criteria
指定查询条件,这种方式胜在随处可用,但需要引入 MongoTemplate
对象:
@Autowired
private MongoTemplate mongoTemplate;
举个例子,写一个支持名字和年龄查询的方法:
@RequestMapping("/getUserByQuery/{name}/{date}")
public List<User> getUserByQuery(@PathVariable String name, @PathVariable int age){
// 指定查询的集合
String collectionName = "user";
// 构造查询对象
Query query = Query.query(Criteria.where("name").regex(".*" + name + ".*", "i")
.and("age").gte(age));
// 调用 mongoTemplate 查询
List<User> users = mongoTemplate.find(query, User.class, collectionName);
return users;
}
其中的 Criteria
就是查询条件了,通过链式编程的方式可以一直往下写。最后通过 mongoTemplate
对象进行查询,注意需要指定查询的集合。
如请求 /getUserByGreaterThanDate/qiyuan/2023-05-01
查询名字包括 qiyuan 且年龄大于等于 21 的用户:
[{"userId":"0723","name":"Qiyuan","age":21,"createDate":"2023-05-06T02:46:28.598+00:00"}]
使用 Query 对象查询的方式本质还是构造 MongoDB 原生的查询语句去查询,如上面这个查询参数对应的就是
Query: { "name" : { "$regularExpression" : { "pattern" : ".*qiyuan.*", "options" : "i"}}, "age" : { "$gte" : 21}}, Fields: {}, Sort: {}
因此这种方式可以说是最灵活的了,可以指定的东西非常多。
总结
在 MongoDB 中尝试了基本的新增、查询操作,还有修改、查询没搞。其实是因为修改搞半天搞不好,累了,下次再说吧。
标签:00,SpringBoot,MongoDB,age,userId,查询,createDate,name From: https://www.cnblogs.com/qiyuanc/p/Back15.html