
MongoDB动态条件之分页查询
发布日期:2025-04-14 14:52:36
浏览次数:8
分类:精选文章
本文共 6683 字,大约阅读时间需要 22 分钟。
MongoDB 在 Spring Data 中的应用通常涉及多种查询方法,本文将从多个角度探讨如何高效地与 MongoDB 数据库交互。
一、基于 MongoRepository 的实现
最直接的方法是继承 MongoRepository 接口,利用其强大的查询功能。具体实现如下:
public interface StudentRepository extends MongoRepository<, Student> {}
在实现中,主要采用 ExampleMatcher
作为匹配器,支持模糊查询和大小写忽略。以下是典型的代码实现:
public PagegetListWithExample(StudentReqVO studentReqVO) { Sort sort = Sort.by(Sort.Direction.DESC, "createTime"); Pageable pageable = PageRequest.of(studentReqVO.getPageNum(), studentReqVO.getPageSize(), sort); Student student = new Student(); BeanUtils.copyProperties(studentReqVO, student); ExampleMatcher matcher = ExampleMatcher.matching() .withStringMatcher(ExampleMatcher.StringMatcher.CONTAINING) .withIgnoreCase(true) .withMatcher("name", ExampleMatcher.GenericPropertyMatchers.contains()) .withIgnorePaths("pageNum", "pageSize"); Example example = Example.of(student, matcher); Page students = studentRepository.findAll(example, pageable); return students;}
优点:支持模糊查询和复杂条件组合。
缺点:不支持范围查询和过滤条件分组。
二、基于 MongoDB Template 的实现
MongoTemplate 提供了更加灵活的查询方式,以下是两种典型实现。
实现一:使用 Criteria 封装查询条件
public PagegetListWithCriteria(StudentReqVO studentReqVO) { Sort sort = Sort.by(Sort.Direction.DESC, "createTime"); Pageable pageable = PageRequest.of(studentReqVO.getPageNum(), studentReqVO.getPageSize(), sort); Query query = new Query(); if (!StringUtils.isEmpty(studentReqVO.getName())) { Pattern pattern = Pattern.compile("^.*" + studentReqVO.getName() + ".*$", Pattern.CASE_INSENSITIVE); query.addCriteria(Criteria.where("name").regex(pattern)); } if (studentReqVO.getSex() != null) { query.addCriteria(Criteria.where("sex").is(studentReqVO.getSex())); } if (studentReqVO.getCreateTime() != null) { query.addCriteria(Criteria.where("createTime").lte(studentReqVO.getCreateTime())); } long total = mongoTemplate.count(query, Student.class); List studentList = mongoTemplate.find(query.with(pageable), Student.class); PageImpl studentPage = new PageImpl(studentList, pageable, total); return studentPage;}
实现二:结合 Example 和 Criteria
public PagegetListWithExampleAndCriteria(StudentReqVO studentReqVO) { Sort sort = Sort.by(Sort.Direction.DESC, "createTime"); Pageable pageable = PageRequest.of(studentReqVO.getPageNum(), studentReqVO.getPageSize(), sort); Student student = new Student(); BeanUtils.copyProperties(studentReqVO, student); ExampleMatcher matcher = ExampleMatcher.matching() .withStringMatcher(ExampleMatcher.StringMatcher.CONTAINING) .withIgnoreCase(true) .withMatcher("name", ExampleMatcher.GenericPropertyMatchers.contains()) .withIgnorePaths("pageNum", "pageSize"); Example example = Example.of(student, matcher); Query query = new Query(Criteria.byExample(example)); if (studentReqVO.getCreateTime() != null) { query.addCriteria(Criteria.where("createTime").lte(studentReqVO.getCreateTime())); } long total = mongoTemplate.count(query, Student.class); List studentList = mongoTemplate.find(query.with(pageable), Student.class); PageImpl studentPage = new PageImpl(studentList, pageable, total); return studentPage;}
优点:支持复杂查询条件和模糊搜索。
缺点:不支持返回固定字段。
三、基于 BasicQuery 的实现
BasicQuery 是 Query 的子类,支持返回固定字段,查询速度较快,适合大数据量的场景。
public PagegetListWithBasicQuery(StudentReqVO studentReqVO) { Sort sort = Sort.by(Sort.Direction.DESC, "createTime"); Pageable pageable = PageRequest.of(studentReqVO.getPageNum(), studentReqVO.getPageSize(), sort); QueryBuilder queryBuilder = new QueryBuilder(); if (!StringUtils.isEmpty(studentReqVO.getName())) { Pattern pattern = Pattern.compile("^.*" + studentReqVO.getName() + ".*$", Pattern.CASE_INSENSITIVE); queryBuilder.and("name").regex(pattern); } if (studentReqVO.getSex() != null) { queryBuilder.and("sex").is(studentReqVO.getSex()); } if (studentReqVO.getCreateTime() != null) { queryBuilder.and("createTime").lessThanEquals(studentReqVO.getCreateTime()); } BasicDBObject fieldsObject = new BasicDBObject(); fieldsObject.append("id", 1); fieldsObject.append("name", 1); Query query = new BasicQuery(queryBuilder.get().toString(), fieldsObject.toJson()); long total = mongoTemplate.count(query, Student.class); List studentList = mongoTemplate.find(query.with(pageable), Student.class); PageImpl studentPage = new PageImpl(studentList, pageable, total); return studentPage;}
优点:支持固定字段返回和快速查询。
缺点:不支持复杂的聚合操作。
四、基于 Aggregation 的实现
Aggregation 提供了更强大的查询功能,支持分组、聚合等操作。
public PagegetListWithAggregation(StudentReqVO studentReqVO) { Sort sort = Sort.by(Sort.Direction.DESC, "createTime"); Pageable pageable = PageRequest.of(studentReqVO.getPageNum(), studentReqVO.getPageSize(), sort); Integer pageNum = studentReqVO.getPageNum(); Integer pageSize = studentReqVO.getPageSize(); List operations = new ArrayList<>(); if (!StringUtils.isEmpty(studentReqVO.getName())) { Pattern pattern = Pattern.compile("^.*" + studentReqVO.getName() + ".*$", Pattern.CASE_INSENSITIVE); Criteria criteria = Criteria.where("name").regex(pattern); operations.add(Aggregation.match(criteria)); } if (null != studentReqVO.getSex()) { operations.add(Aggregation.match(Criteria.where("sex").is(studentReqVO.getSex()))); } if (operations.size() > 0) { Aggregation aggregationCount = Aggregation.newAggregation(operations); AggregationResults resultsCount = mongoTemplate.aggregate(aggregationCount, "student", Student.class); long totalCount = resultsCount.getMappedResults().size(); } else { List list = mongoTemplate.findAll(Student.class); totalCount = list.size(); } operations.add(Aggregation.skip((long) pageNum * pageSize)); operations.add(Aggregation.limit(pageSize)); operations.add(Aggregation.sort(Sort.Direction.DESC, "createTime")); Aggregation aggregation = Aggregation.newAggregation(operations); AggregationResults results = mongoTemplate.aggregate(aggregation, "student", Student.class); PageImpl studentPage = new PageImpl(results.getMappedResults(), pageable, totalCount); return studentPage;}
优点:支持分组、聚合和复杂查询。
缺点:查询速度较慢,建议用于数据量较小的场景。
总结
以上方法各有优劣,选择时需要根据具体需求决定。基于 Example Matcher 的方法适合支持模糊查询的场景,而 BasicQuery 和 Aggregation 方法则适合需要固定字段返回或复杂聚合的场景。
发表评论
最新留言
路过,博主的博客真漂亮。。
[***.116.15.85]2025年04月28日 06时52分21秒
关于作者

喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
mybatis
2025-04-14
Mobx 结合 TypeScript 实现 setState 类型推导
2025-04-14
MyAdapter代码复用工具类
2025-04-14
Mock 工具使用:弱网测试
2025-04-14
Mock+Proxy在SDK项目的自己主动化測试实战
2025-04-14
Mock.js 的语法规范
2025-04-14
Mock.js 的语法规范学习
2025-04-14
my97日期控件插件的开发与编写
2025-04-14
mockcpp & testngpp在2010.7~11月的改进
2025-04-14
Mock在接口测试中的实际应用
2025-04-14
Mock技术在JAVA微服务单元测试中的应用
2025-04-14
Mock模拟测试实战
2025-04-14
Mock模拟测试框架详解
2025-04-14
mock的使用二(根据数据模板生成模拟数据)
2025-04-14
mock静态方法指引
2025-04-14
Modbus Poll/Slave 模拟器使用教程
2025-04-14
Modbus RTU串口通信实验
2025-04-14
Modbus RTU和Modbus TCP之间的区别
2025-04-14
MODBUS 线圈、输入线圈、输入寄存器、保持输出寄存器的存储规范标识与功能码
2025-04-14