MongoDB动态条件之分页查询
发布日期:2025-04-14 14:52:36 浏览次数:8 分类:精选文章

本文共 6683 字,大约阅读时间需要 22 分钟。

MongoDB 在 Spring Data 中的应用通常涉及多种查询方法,本文将从多个角度探讨如何高效地与 MongoDB 数据库交互。


一、基于 MongoRepository 的实现

最直接的方法是继承 MongoRepository 接口,利用其强大的查询功能。具体实现如下:

public interface StudentRepository extends MongoRepository<, Student> {}

在实现中,主要采用 ExampleMatcher 作为匹配器,支持模糊查询和大小写忽略。以下是典型的代码实现:

public Page
getListWithExample(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 Page
getListWithCriteria(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 Page
getListWithExampleAndCriteria(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 Page
getListWithBasicQuery(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 Page
getListWithAggregation(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 方法则适合需要固定字段返回或复杂聚合的场景。

上一篇:MX Linux 23.4 发布!基于 Debian 12.7,修复了大量错误
下一篇:mxGraph改变图形大小重置overlay位置

发表评论

最新留言

路过,博主的博客真漂亮。。
[***.116.15.85]2025年04月28日 06时52分21秒