You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在MongoDB Spring Data中对多字段进行聚合统计?

MongoDB Spring Data 实现多数组字段内userId的聚合计数

咱们先明确需求:现有订单数据里包含manageremployee两个数组字段,每个数组里存着带userId的对象,需要把这两个字段里的所有userId合并起来统计出现次数,最终输出一个包含统计结果数组的Agg字段。

核心思路(先看MongoDB原生聚合逻辑)

要实现这个需求,聚合管道需要分这几步走:

  1. 合并数组:把manager.userIdemployee.userId两个数组合并成一个包含所有userId的数组
  2. 拆分数组:将合并后的数组拆分为单个文档,每个文档对应一个userId
  3. 分组统计:按userId分组,统计每个userId出现的总次数
  4. 调整格式:把统计结果整理成指定的键名,最后打包到Agg数组中

Spring Data MongoDB 代码实现

首先可以定义两个简单的DTO来接收最终结果:

// 单个用户的统计结果
public class UserCount {
    private String userId;
    private int total;

    // 构造器、getter、setter 省略
}

// 最终聚合结果
public class AggregationResult {
    private List<UserCount> Agg;

    // 构造器、getter、setter 省略
}

然后用Aggregation类构建聚合管道,通过MongoTemplate执行:

@Autowired
private MongoTemplate mongoTemplate;

public AggregationResult countUserIds() {
    // 1. 合并manager和employee的userId数组
    ProjectionOperation projectAllUserIds = Aggregation.project()
            .and(Aggregation.concatArrays("manager.userId", "employee.userId"))
            .as("allUserIds");

    // 2. 拆分合并后的数组
    UnwindOperation unwindUserIds = Aggregation.unwind("allUserIds");

    // 3. 按userId分组统计次数
    GroupOperation groupByUserId = Aggregation.group("allUserIds")
            .count().as("total");

    // 4. 调整字段名,匹配期望输出
    ProjectionOperation projectFinalFields = Aggregation.project("total")
            .and("allUserIds").as("userId");

    // 5. 将所有统计结果打包到Agg数组中
    GroupOperation wrapIntoAggArray = Aggregation.group()
            .push(Aggregation.fields().and("userId").and("total")).as("Agg");

    // 构建聚合管道并执行
    Aggregation aggregation = Aggregation.newAggregation(
            projectAllUserIds,
            unwindUserIds,
            groupByUserId,
            projectFinalFields,
            wrapIntoAggArray
    );

    AggregationResults<AggregationResult> results = mongoTemplate.aggregate(
            aggregation,
            "your-collection-name", // 替换成你的集合名称
            AggregationResult.class
    );

    return results.getUniqueMappedResult();
}

代码解释

  • concatArrays:把两个数组里的userId提取出来合并成一个数组,这样不管是manager还是employee的userId都被放到同一个集合里
  • unwind:把数组拆成单个文档,确保每个userId都能被单独统计
  • group("allUserIds").count():按userId分组,统计每个userId出现的总次数
  • 最后一步的group().push(...):把所有统计后的用户对象打包到Agg数组中,完全匹配你期望的输出格式

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

火山引擎 最新活动