Springboot整合MongoDB系列(三) | 您所在的位置:网站首页 › springboot整合mongo官网 › Springboot整合MongoDB系列(三) |
我们继续MongoDB系列博客的第三篇,记录下springboot整合MongoDB的基本curd操作,各位看到此博客的小伙伴,如有不对的地方请及时通过私信我或者评论此博客的方式指出,以免误人子弟。多谢! 目录 测试环境准备 测试MongoTemplate的curd insert 操作 save:没有则创建,存在则更新 删除操作 修改操作 基本查询、范围查询、模糊查询 排序 分页查询 管道Aggregation查询 管道Aggregation分页查询 通过BasicQuery指定返回的字段 通过Aggregation.project指定返回的字段 测试环境准备测试环境的准备工作就不贴图了,就是创建一个springboot项目,贴一下测试用到的实体类和pom依赖 @Data @Builder @Document("user") public class User { private String username; private String sex; private String address; private String createTime; private Integer age; } 4.0.0 org.springframework.boot spring-boot-starter-parent 2.3.3.RELEASE com.example mongo 0.0.1-SNAPSHOT mongo Demo project for Spring Boot 1.8 org.springframework.boot spring-boot-starter-test test org.springframework.boot spring-boot-starter-web org.projectlombok lombok true org.springframework.boot spring-boot-starter-data-mongodb com.alibaba fastjson 1.2.56 commons-io commons-io 2.6 org.springframework.boot spring-boot-maven-plugin org.projectlombok lombok测试数据 public User getUser(){ return User.builder().username("zhaoliu").age(10).sex("男").address( "rizhao").build(); } public List getUserList(){ User user2 = User.builder().username("zhangsan").age(10).sex("男").address("jinan").build(); User user3 = User.builder().username("lisi").age(20).sex("女").address("jinan").build(); List userList = new ArrayList(); userList.add(user2); userList.add(user3); return userList; } public void clearDb(){ mongoTemplate.dropCollection(User.class); } 测试MongoTemplate的curd insert 操作 @Test public void insert(){ clearDb(); // insert one User user = getUser(); User user1 = mongoTemplate.insert(user); // insert many List userList = getUserList(); mongoTemplate.insert(userList,User.class); //mongoTemplate.insertAll(userList); }查看数据库结果如下: 如上,上面我们构建User对象时,并没有为createTime属性赋值,也没有为id属性赋值,在保存后,数据库中并没有createTime, 不同于保存mysql 对象属性不赋值会有默认保存进数据库, 比如这个字符串类型的createTime 会默认为空保存,并且也没有id属性,但是保存时mongoDB会默认生成一个Object类型的_id。 上面我们User试题中并没有id属性,保存后在数据库中默认生成了一个Object类型的_id,看下加上id属性后的效果: private String id;同样执行上面的测试方法,执行结果如下: 如上:虽然我们在User对象中加了id属性,但是保存时并没有单独的id字段,id会自动映射成"_id"吗?测试一下: User user = User.builder().id("qazwsx").username("zhaoliu").age(20).sex("男").address("rizhao").build();我们为id赋值,再次保存后,发现_id的值为qazwsx,可以确定id属性自动映射成了 _id。 我们不想让id自动映射为_id,就想要数据库中保存id怎么办呢,可以使用@Field显示的指定它对应的属性名。 也可以使用@Field注解指定保存到数据库中字段的名字,比如指定User对象id属性保存到数据库中为uid,可以这样: @Field("uid") private String id; User user2 = User.builder().id("zbc").username("yjh").age(18).build(); mongoTemplate.insert(user2);执行结果如下: 如果我们既不想使用数据库默认生成的_id,也不想用id自动映射的 _id,可以使用@Id注解标识任意字段为数据库的 _id,比如使用@Id标识username属性,保存后username就会作为数据库的 _id。当然一般我们不会这么办,毕竟username作为主键还是不合适的,这里只是为了测试。 @Id private String username;数据库结果如下: 简单总结下保存时的一些细节: 1.保存时mongoDB会默认生成一个Object类型的_id。 2.不初始化属性,保存后数据库没有此filed。 3.执行保存时在java class中的id属性,会自动映射成"_id"。 4.使用@Id标记的字段也会在数据库中显示为_id 接下来的就只贴测试方法不在贴数据库截图了,大家感兴趣可以自己在本地试下: save:没有则创建,存在则更新 @Test public void save(){ clearDb(); // id为 610253fe88164b310a41ca2f 的数据age修改为100 User user = User.builder().id("610253fe88164b310a41ca2f").username("zhaoliu").sex("男").age(100).build(); mongoTemplate.save(user); // 创建testuser集合 并新增一条数据 mongoTemplate.save(user,"testuser"); } 删除操作 @Test public void delete(){ Query query = new Query(); Criteria criteria = Criteria.where("_id").is("60ec045d0c385469452d1c21"); query.addCriteria(criteria); mongoTemplate.remove(query,User.class); Query query1 = new Query(Criteria.where("_id").ne("60ec0c56b0f4dc6363dfc02a")); mongoTemplate.remove(query1,"testuser"); // delete all datas in collection mongoTemplate.dropCollection(User.class); // delete collection mongoTemplate.dropCollection("mytest1"); } 修改操作 /** * Update.update(key,value)也可完成修改 ---> 修改一个字段 * Update.update(key,value).set("key,value) ---> 修改两个字段 * Update.update(key,value).set("key,value).set(key,value).set...... ---> 修改多个字段 * 1.修改满足条件的第一条数据 使用updateFirst * 2.修改满足条件的所有数据 使用updateMulti * 3.upsert: 按条件查询 查询到数据则修改 没查询到则添加 并且upsert只会更新匹配到的第一条数据 * 如下:若查询到有username为wangwu的数据则将sex改为男 * 若没查询到有username为wangwu的数据则新插入一条数据(username:wangwu sex:男) */ @Test public void update(){ /*ObjectId objectId = new ObjectId("60ee4af0771c712494b9ac4d"); Query query = new Query(); Criteria criteria = Criteria.where("_id").is(objectId); query.addCriteria(criteria); Update update = new Update(); update.set("username","zhangsan");*/ Criteria criteria = Criteria.where("username").is("lisi123"); Query query = Query.query(criteria); Update update = Update.update("username", "lisi"); //mongoTemplate.updateFirst(query,update,User.class); //mongoTemplate.updateMulti(query,update,User.class); //mongoTemplate.upsert(query,update,User.class); Criteria criteria1 = Criteria.where("username").is("wangwu"); Query query1 = Query.query(criteria1); Update update1 = Update.update("sex","男"); mongoTemplate.upsert(query1,update1,User.class); } 基本查询、范围查询、模糊查询需要注意的是范围查询,范围查询需要使用Criteria 的andOperator(Criteria... criteria)方法,比如按照age的范围进行查询时需要这样写: Criteria criteria3 = new Criteria(); criteria3.andOperator(Criteria.where("age").gt(10),Criteria.where("age").lt(50)); 而不能像追加多个条件一样使用如下的方式: Criteria criteria3 = Criteria.where("age").gt(10).and("age").lt(50); Criteria criteria3 = new Criteria(); criteria3.and("age").gt(10); criteria3.and("age").lt(50);否则会报如下错误: InvalidMongoDbApiUsageException: Due to limitations of the com.mongodb.BasicDocument, you can't add a second 'age' expression specified as 'age : Document{{$lt=50}}'. Criteria already contains 'age : Document{{$gt=10}}'. /** * 基本查询 模糊查询 范围查询 * 使用regex(Pattern pattern) 实现模糊查询 * 完全匹配:Pattern pattern = Pattern.compile("^张$", Pattern.CASE_INSENSITIVE); * 右匹配:Pattern pattern = Pattern.compile("^.*张$", Pattern.CASE_INSENSITIVE); * 左匹配:Pattern pattern = Pattern.compile("^张.*$", Pattern.CASE_INSENSITIVE); * 模糊匹配:Pattern pattern = Pattern.compile("^.*张.*$", Pattern.CASE_INSENSITIVE); */ @Test public void select(){ Criteria criteria = Criteria.where("username").is("wangwu"); Query query = Query.query(criteria); List userList = mongoTemplate.find(query, User.class); System.out.println(userList); List all = mongoTemplate.findAll(User.class); System.out.println(all); // 模糊查询 Pattern pattern = Pattern.compile("^lisi.*$", Pattern.CASE_INSENSITIVE); Criteria criteria1 = Criteria.where("username").regex(pattern); Query query1 = Query.query(criteria1); User user = mongoTemplate.findOne(query1, User.class); System.out.println(user); Criteria criteria2 = Criteria.where("_id").is("60ee4af0771c712494b9ac4d"); Query query2 = Query.query(criteria2); User user1 = mongoTemplate.findOne(query2, User.class); System.out.println(user1); User user2 = mongoTemplate.findById("60ee4af0771c712494b9ac4d", User.class); System.out.println(user2); long count = mongoTemplate.count(query, User.class); System.out.println(count); boolean exists = mongoTemplate.exists(query, User.class); System.out.println(exists); // 范围查询 // InvalidMongoDbApiUsageException: Due to limitations of the com.mongodb.BasicDocument, you can't add a second 'age' expression specified as 'age : Document{{$lt=50}}'. Criteria already contains 'age : Document{{$gt=10}}'. // Criteria criteria3 = Criteria.where("age").gt(10).and("age").lt(50); // Criteria criteria3 = new Criteria(); criteria3.and("age").gt(10); criteria3.and("age").lt(50); Criteria criteria3 = new Criteria(); criteria3.andOperator(Criteria.where("age").gt(10),Criteria.where("age").lt(50)); Query query3 = Query.query(criteria3); List userList1 = mongoTemplate.find(query3, User.class); System.out.println(userList1); // 查询指Map定collection中的数据 Criteria criteria10 = Criteria.where("name").is("zhangsan"); Query query10 = Query.query(criteria10); List testuser = mongoTemplate.find(query10, Map.class,"testuser"); System.out.println(testuser); } 排序 /** * 排序 * 1.默认升序 Sort.by("age") * 2.可通过Sort.by(Sort.Order.desc("age")) 或 Sort.by(Sort.Direction.DESC,"age") 指定排序方式 * 3. */ @Test public void select1(){ Query query = new Query(); Sort sort = Sort.by("age"); query.with(sort); List userList = mongoTemplate.find(query, User.class); System.out.println(userList); Sort sort1 = Sort.by(Sort.Order.desc("age")); query.with(sort1); List userList1 = mongoTemplate.find(query, User.class); System.out.println(userList1); Sort sort2 = Sort.by(Sort.Direction.DESC,"age"); query.with(sort2); List userList2 = mongoTemplate.find(query, User.class); System.out.println(userList2); } 分页查询 @Test public void select2(){ Pageable page = PageRequest.of(0, 2); Query query = new Query(); query.with(page); List userList = mongoTemplate.find(query, User.class); System.out.println(userList + "---" + userList.size()); Sort sort = Sort.by("age"); Pageable pageable = PageRequest.of(0,2,sort); Query query1 = new Query(); query1.with(pageable); List userList1 = mongoTemplate.find(query1, User.class); System.out.println(userList1); Pageable pageable1 = PageRequest.of(0, 2, Sort.Direction.DESC, new String[]{"age"}); Query query2 = new Query(); query2.with(pageable1); List userList2 = mongoTemplate.find(query2, User.class); System.out.println(userList2); // 分页1 long count = mongoTemplate.count(new Query(), User.class); System.out.println(count); Page userPage = new PageImpl(userList2,pageable1,count); System.out.println("---getTotalElements---" + userPage.getTotalElements());// 总记录数 System.out.println("---getTotalPages---" + userPage.getTotalPages());// 总页数 System.out.println("---getNumber---" + userPage.getNumber());// 当前页 System.out.println("---getSize---" + userPage.getSize());// 每页大小 System.out.println("---getContent---" + userPage.getContent()); // 数据 System.out.println("---getNumberOfElements---" + userPage.getNumberOfElements());// 当前页的元素数 // 分页2 Page userPage1 = PageableExecutionUtils.getPage(userList2, pageable1, () -> count); System.out.println("---getTotalElements---" + userPage1.getTotalElements());// 总记录数 System.out.println("---getTotalPages---" + userPage1.getTotalPages());// 总页数 System.out.println("---getNumber---" + userPage1.getNumber());// 当前页 System.out.println("---getSize---" + userPage1.getSize());// 每页大小 System.out.println("---getContent---" + userPage1.getContent()); // 数据 System.out.println("---getNumberOfElements---" + userPage1.getNumberOfElements());// 当前页的元素数 } 管道Aggregation查询 /** * AggregationResults 一般用查询的类接就好 * [Document{{_id=60ee4af0771c712494b9ac4d, age=30.0}}, Document{{_id=60ee9cd8d82d3d76d2ed2204, age=30.0}}] * [User(id=60ee4af0771c712494b9ac4d, username=null, password=null, sex=null, address=null, createTime=null, age=30), User(id=60ee9cd8d82d3d76d2ed2204, username=null, password=null, sex=null, address=null, createTime=null, age=30)] */ @Test public void aggregation(){ // select * from user where age > 20 Criteria criteria = Criteria.where("age").gt(20); // 使用List封装查询条件 或者直接用Aggregation构建 如:Aggregation.match(criteria) List operations = new ArrayList(); operations.add(Aggregation.match(criteria)); TypedAggregation aggregation = Aggregation.newAggregation(User.class,operations); AggregationResults aggregationResults = mongoTemplate.aggregate(aggregation, Document.class); System.out.println(aggregationResults.getMappedResults()); // select age,count(*) from user group by age List operations1 = new ArrayList(); operations1.add(Aggregation.group("age").sum("age").as("counts")); TypedAggregation typedAggregation = TypedAggregation.newAggregation(User.class, operations1); AggregationResults aggregationResults1 = mongoTemplate.aggregate(typedAggregation, User.class); System.out.println(aggregationResults1.getMappedResults()); Set names = new HashSet(); names.add("lisi"); names.add("wangwu"); Aggregation agg = Aggregation.newAggregation( Aggregation.match(Criteria.where("username").in(names)), Aggregation.match(Criteria.where("age").gt(10)) ); AggregationResults aggregationResults2 = mongoTemplate.aggregate(agg, "user", User.class); System.out.println(aggregationResults2.getMappedResults()); } 管道Aggregation分页查询 @Test public void aggregation1(){ int pageNum = 0; int pageSize = 2; Pageable pageable = PageRequest.of(pageNum,pageSize); int totalCount; // 查询条件 List operations = new ArrayList(); // 模拟一下带条件的查询 String username = "zhaoliu"; if(StringUtils.isNotBlank(username)){ operations.add(Aggregation.match(Criteria.where("username").ne("zhaoliu"))); Aggregation aggregation = Aggregation.newAggregation(operations); AggregationResults aggregationResults = mongoTemplate.aggregate(aggregation, "user", User.class); totalCount = aggregationResults.getMappedResults().size(); }else{ totalCount = mongoTemplate.findAll(User.class).size(); } // 分页信息 operations.add(Aggregation.skip((long)pageNum * pageSize)); operations.add(Aggregation.limit(pageSize)); // 排序 或者在Pageable中添加排序 operations.add(Aggregation.sort(Sort.Direction.DESC, "age")); //当前页数据 Aggregation aggregation = Aggregation.newAggregation(operations); AggregationResults results = mongoTemplate.aggregate(aggregation, "user", User.class); // 分页查询 Page userPage = PageableExecutionUtils.getPage(results.getMappedResults(), pageable, () -> totalCount); System.out.println("---getTotalElements---" + userPage.getTotalElements());// 总记录数 System.out.println("---getTotalPages---" + userPage.getTotalPages());// 总页数 System.out.println("---getNumber---" + userPage.getNumber());// 当前页 System.out.println("---getSize---" + userPage.getSize());// 每页大小 System.out.println("---getContent---" + userPage.getContent()); // 数据 System.out.println("---getNumberOfElements---" + userPage.getNumberOfElements());// 当前页的元素数 } 通过BasicQuery指定返回的字段 /** * 通过BasicQuery指定返回的字段 * 不设置的属性字段值为null * 如:[User(id=60ee4af0771c712494b9ac4d, username=lisi, sex=女, address=null, createTime=null, age=20)] */ @Test public void select3(){ // 查询条件 BasicDBObject dbObject = new BasicDBObject(); dbObject.put("username", "lisi"); //指定返回的字段 BasicDBObject fieldsObject = new BasicDBObject(); fieldsObject.put("username",true); fieldsObject.put("age",true); fieldsObject.put("sex",true); Query query = new BasicQuery(dbObject.toJson(),fieldsObject.toJson()); List userList = mongoTemplate.find(query, User.class); System.out.println(userList); } 通过Aggregation.project指定返回的字段 /** * 通过Aggregation.project指定返回的字段 * project :控制返回的字段,例如一个实体类,我们只需要部分字段 * 同上面一样通过对象接收结果时,没设置的属性值为null * 如:[User(id=60ee4af0771c712494b9ac4d, username=lisi, password=null, sex=女, address=null, createTime=null, age=20)] * 我们可以使用Map接收 * 如:[{_id=60ee4af0771c712494b9ac4d, username=lisi, sex=女, age=20.0}] * 综上两种方式,如果只想返回指定字段,可以使用map类型来接收返回结果,但是也要看返回数据的结构是否利于后续解析 * 如果结构复杂,用对象的方式会方便些,虽然有一些我们不需要的属性,但是在最终接口返回前可以转换一下去掉不需要的属性 */ @Test public void select4(){ Criteria criteria = Criteria.where("username").is("lisi"); MatchOperation match = Aggregation.match(criteria); ProjectionOperation project = Aggregation.project("username","age","sex"); Aggregation aggregation = Aggregation.newAggregation(match,project); AggregationResults results = mongoTemplate.aggregate(aggregation, "user", User.class); System.out.println(results.getMappedResults()); AggregationResults results1 = mongoTemplate.aggregate(aggregation, "user", Map.class); System.out.println(results1.getMappedResults()); } |
CopyRight 2018-2019 实验室设备网 版权所有 |