Java分页查询MongoDB能否仅调用一次数据库?
能否通过单次MongoDB调用同时获取分页数据与总文档数?
当pageSize设为10、pageNumber设为0时,若MongoDB中符合查询条件的文档共有50条,我们需要同时返回两个结果:
total_documents:总文档数50msList:前10条文档的NSDTO详情
目前的实现通过两次MongoDB调用完成,代码如下:
Query query = new Query(); List<Criteria> criteria = new ArrayList<>(); criteria.add(Criteria.where("di.ai").in(new ArrayList<>(Arrays.asList("123")))); query.addCriteria(new Criteria().andOperator(criteria.toArray(new Criteria[criteria.size()]))); Long total_documents = this.mongoTemplate.count(query, NSDTO.class, MONGODB_MESSAGE_COLLECTION); Pageable pageable = PageRequest.of((pageNumber - 1), pageSize); query.with(pageable); List<NSDTO> nsList= this.mongoTemplate.find(query, NSDTO.class, MONGODB_MESSAGE_COLLECTION);
可以通过单次MongoDB调用实现需求,利用MongoDB的聚合框架中的$facet阶段,在一个聚合请求中同时计算总文档数和分页数据。
实现代码示例
// 构建查询条件 Criteria criteria = Criteria.where("di.ai").in(Arrays.asList("123")); // 定义聚合管道 Aggregation aggregation = Aggregation.newAggregation( // 匹配查询条件 Aggregation.match(criteria), // 分面查询:同时执行两个子管道 Aggregation.facet( // 子管道1:计算总文档数 Aggregation.newAggregation( Aggregation.count().as("total") ).withOutput("total_documents"), // 子管道2:分页获取数据(pageNumber从0开始时,直接用pageNumber*pageSize计算偏移量) Aggregation.newAggregation( Aggregation.skip(pageNumber * pageSize), Aggregation.limit(pageSize), // 映射字段,确保和NSDTO的属性对应(可根据实际DTO结构调整) Aggregation.project() .and("field1").as("field1") .and("di.ai").as("di.ai") // 补充其他需要映射的字段 ).withOutput("msList") ) ); // 执行聚合查询 AggregationResults<Map<String, Object>> results = mongoTemplate.aggregate( aggregation, MONGODB_MESSAGE_COLLECTION, Map.class ); // 解析返回结果 Map<String, Object> resultMap = results.getUniqueMappedResult(); List<Map<String, Object>> totalResult = (List<Map<String, Object>>) resultMap.get("total_documents"); Long total_documents = ((Number) totalResult.get(0).get("total")).longValue(); // 将文档列表转换为NSDTO对象列表 List<NSDTO> msList = mongoTemplate.getConverter().convertToList( NSDTO.class, (List<Document>) resultMap.get("msList") );
关键说明
$facet阶段允许在一个聚合请求中定义多个独立子管道,分别完成总计数、分页查询的逻辑,最终将所有子管道的结果合并到同一返回文档中,彻底避免两次MongoDB调用。- 原代码中
PageRequest.of((pageNumber - 1), pageSize)存在逻辑问题:当pageNumber为0时,会生成skip(-10)的非法指令。如果分页页码从0开始,直接用pageNumber * pageSize计算偏移量即可;若页码从1开始,才需要用(pageNumber - 1)*pageSize。
内容的提问来源于stack exchange,提问作者Swetha
相关产品推荐
相关产品推荐

