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

MongoDB多分组聚合查询及Spring Data实现问题咨询

解决MongoDB分组统计唯一手机号的问题

咱们先明确需求核心:你要统计指定CAMPAIGN_ID下,每个MESSAGE_CONFIG_ID对应的已送达(DELIVRD)的唯一手机号数量,而不是所有送达记录的条数。之前的代码没有对手机号做去重处理,导致同一个手机号被重复统计,所以结果不符合预期。

一、Mongo Shell 正确实现代码

我们需要分两步分组:先对MESSAGE_CONFIG_ID+mobile去重,再按MESSAGE_CONFIG_ID统计去重后的手机号数量:

db.getCollection('GROUP_ID_DELIVERY_STATUS').aggregate([
    // 第一步:过滤指定CAMPAIGN_ID的文档
    { "$match": {"CAMPAIGN_ID": "5a70252612d91c7b085df083"} },
    // 第二步:展开DATA_LIST数组,把每个数组元素变成独立文档
    { "$unwind": "$DATA_LIST" },
    // 第三步:只保留状态为DELIVRD的送达记录
    { "$match": {"DATA_LIST.status": "DELIVRD"} },
    // 第四步:按MESSAGE_CONFIG_ID和mobile分组,实现去重(同一个MESSAGE_CONFIG_ID下的同一个手机号只留一条)
    { "$group": {
        "_id": {
            "MESSAGE_CONFIG_ID": "$MESSAGE_CONFIG_ID",
            "mobile": "$DATA_LIST.mobile"
        }
    } },
    // 第五步:按MESSAGE_CONFIG_ID分组,统计去重后的手机号数量
    { "$group": {
        "_id": "$_id.MESSAGE_CONFIG_ID",
        "unique_delivered_mobile_count": { "$sum": 1 }
    } },
    // 可选:重命名字段让结果更直观
    { "$project": {
        "_id": 0,
        "MESSAGE_CONFIG_ID": "$_id",
        "unique_delivered_mobile_count": 1
    } }
])

代码解释:

  • 前三个阶段和你原来的一致:过滤目标活动、展开数组、筛选已送达记录。
  • 第四个$group是关键:通过MESSAGE_CONFIG_ID+mobile作为分组ID,自动去重同一个配置下的重复手机号。
  • 第五个$group统计每个配置下的唯一手机号总数,最后用$project调整输出格式,让结果更易读。

二、Spring Data MongoDB 正确实现代码

对应上面的聚合逻辑,用Spring Data的AggregationAPI实现:

import org.springframework.data.mongodb.core.aggregation.Aggregation;
import static org.springframework.data.mongodb.core.aggregation.Aggregation.*;

// 构建聚合操作
Aggregation aggregation = newAggregation(
    // 过滤指定CAMPAIGN_ID
    match(Criteria.where("CAMPAIGN_ID").is("5a70252612d91c7b085df083")),
    // 展开DATA_LIST数组
    unwind("DATA_LIST"),
    // 筛选已送达的记录
    match(Criteria.where("DATA_LIST.status").is("DELIVRD")),
    // 第一步分组:按MESSAGE_CONFIG_ID和mobile去重
    group("MESSAGE_CONFIG_ID", "DATA_LIST.mobile"),
    // 第二步分组:按MESSAGE_CONFIG_ID统计数量
    group("_id.MESSAGE_CONFIG_ID").count().as("unique_delivered_mobile_count"),
    // 调整输出格式
    project("unique_delivered_mobile_count").and("_id").as("MESSAGE_CONFIG_ID").andExclude("_id")
);

// 执行聚合查询(假设你有MongoTemplate实例)
// AggregationResults<DeliveryStatsDto> results = mongoTemplate.aggregate(aggregation, "GROUP_ID_DELIVERY_STATUS", DeliveryStatsDto.class);

代码解释:

  • 前三个操作和你原来的一致,重点在两次分组:
    1. 第一次group("MESSAGE_CONFIG_ID", "DATA_LIST.mobile")实现去重,此时每个分组对应一个唯一的配置+手机号组合。
    2. 第二次group("_id.MESSAGE_CONFIG_ID").count().as(...)统计每个配置下的唯一手机号数量。
  • 最后用project调整输出字段,把分组ID转为MESSAGE_CONFIG_ID,并排除默认的_id字段,让结果结构更清晰。

配套结果DTO:

你需要创建一个对应的DTO类来接收返回数据,比如:

public class DeliveryStatsDto {
    private String MESSAGE_CONFIG_ID;
    private long unique_delivered_mobile_count;

    // 构造器、getter、setter方法
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 06:34:57