如何减少MongoDB查询次数:合并基础查询与聚合查询为单次操作
将MongoDB基础查询与聚合查询合并为单次查询
我在MongoDB的sample_collection集合中有以下示例数据:
{"version": "1.1", "platformName": "A", "uri": "https://example.com/1e2b59da-44c1-44a4-aa03-b4487bde0c71" } { "version": "1.1", "platformName": "B", "uri": "https://example.com/1e2b59da-44c1-44a4-aa03-b4487bde0c72" } { "version": "1.1", "platformName": "A", "uri": "https://example.com/1e2b59da-44c1-44a4-aa03-b4487bde0c73" }
我需要统计不同platformName的数量(比如平台A计数为2,平台B计数为1),目前的实现需要执行两次查询:先通过BasicQuery获取匹配的文档,再用聚合查询统计数量,代码如下:
public List<CountDto> groupByFieldName(String fieldName, BasicQuery basicQuery) { basicQuery.fields().include("id"); List<LcaProduct> lcaProductList = mongoTemplate.find(basicQuery, LcaProduct.class, "sample_collection"); List<String> productNames = lcaProductList.parallelStream().map(lcaProduct -> lcaProduct.getPlatformName()).collect(Collectors.toList()); Aggregation aggregation = newAggregation( match(Criteria.where("platformName").in(productNames)), group(fieldName) .first(fieldName).as("name") .count().as("count") ); AggregationResults<CountDto> results = mongoTemplate.aggregate(aggregation, "sample_collection", CountDto.class); return results.getMappedResults(); }
现在希望将两次查询合并为一次,直接通过聚合查询得到统计结果。
解决方案
完全可以将基础查询的条件直接整合到聚合管道中,不需要先查询文档再筛选。核心思路是把BasicQuery中的查询条件作为聚合管道的第一个match阶段,后续直接分组统计即可。
修改后的代码如下:
public List<CountDto> groupByFieldName(String fieldName, BasicQuery basicQuery) { // 直接将BasicQuery的查询条件转换为聚合的match阶段 Aggregation aggregation = newAggregation( match(Criteria.byExample(basicQuery.getQueryObject())), group(fieldName) .first(fieldName).as("name") .count().as("count") ); AggregationResults<CountDto> results = mongoTemplate.aggregate(aggregation, "sample_collection", CountDto.class); return results.getMappedResults(); }
说明
- 复用基础查询条件:通过
basicQuery.getQueryObject()获取原始查询的DBObject,再用Criteria.byExample()转换为聚合可识别的匹配条件,把原来的基础查询逻辑直接放到聚合管道的第一步。 - 单次聚合完成统计:聚合管道先筛选出符合条件的文档,再按指定字段(这里是
platformName)分组并统计数量,全程只需要一次数据库查询。 - 结果映射不变:最终返回的
CountDto列表和原逻辑完全一致,包含每个分组的name(平台名称)和count(数量)。
这样修改后,既避免了两次查询的性能开销,也简化了代码逻辑。
内容的提问来源于stack exchange,提问作者Zeeshan Ali
相关产品推荐
相关产品推荐

