You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何减少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();
}

说明

  1. 复用基础查询条件:通过basicQuery.getQueryObject()获取原始查询的DBObject,再用Criteria.byExample()转换为聚合可识别的匹配条件,把原来的基础查询逻辑直接放到聚合管道的第一步。
  2. 单次聚合完成统计:聚合管道先筛选出符合条件的文档,再按指定字段(这里是platformName)分组并统计数量,全程只需要一次数据库查询。
  3. 结果映射不变:最终返回的CountDto列表和原逻辑完全一致,包含每个分组的name(平台名称)和count(数量)。

这样修改后,既避免了两次查询的性能开销,也简化了代码逻辑。


内容的提问来源于stack exchange,提问作者Zeeshan Ali

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 22:57:47