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

如何将MongoDB聚合查询转为BSON并在Golang中执行及结果排查

问题排查与修复方案

核心问题分析

对比手动查询和代码生成的查询,结合Golang实现细节,三个关键问题导致返回空数据:

1. 空date条件错误过滤数据

当未传入DateFrom和DateTo时,代码将date初始化为空bson.M{}并加入$match条件。MongoDB会把{"date": {}}解析为匹配date字段值为空对象的文档,而非忽略该条件,直接过滤掉所有不符合此规则的文档,导致无结果返回。

2. mid类型不匹配

手动查询中mid的查询值是字符串"81",但代码通过convertToInt将输入字符串转为整数81。如果MongoDB集合中mid字段存储的是字符串类型,整数无法匹配字符串值,自然查不到数据。

3. Aggregate方法参数构造错误

代码调用Aggregate时使用mongo.Pipeline(primary_collection, group_collection),但mongo.Pipeline本质是[]bson.M类型,直接传入两个独立的bson.M会导致Pipeline结构异常,无法正确执行聚合逻辑。


修复后的代码

调整后的GetApnDataFromMongo函数

func GetApnDataFromMongo(data utils.Data, clientName string) (utils.Results, error) {
    result := utils.Results{}

    // 初始化match条件,仅添加有效字段
    matchCond := bson.M{}

    // 保留mid的字符串类型,避免类型不匹配(若mid实际为整数,可恢复convertToInt)
    if len(data.MessageId) > 0 {
        matchCond["mid"] = bson.M{"$in": data.MessageId}
    }

    // 仅当DateFrom和DateTo都存在时,才添加日期过滤条件
    if data.DateFrom != "" && data.DateTo != "" {
        matchCond["date"] = bson.M{"$gte": data.DateFrom, "$lte": data.DateTo}
    }

    primary_collection := bson.M{"$match": matchCond}
    group_collection := bson.M{"$group": bson.M{
        "_id": "$mid",
        "published": bson.M{"$sum": "$published"},
        "sent": bson.M{"$sum": "$sent"},
        "failed": bson.M{"$sum": "$failed"},
        "freqDrop": bson.M{"$sum": "$freqDrop"},
        "delivered": bson.M{"$sum": "$delivered"},
        "clicked": bson.M{"$sum": "$open"},
    }}

    // 正确构造Pipeline
    fullquery := mongo.Pipeline{primary_collection, group_collection}
    jsonString, _ := json.Marshal(fullquery)
    logrus.Info(fmt.Sprintf("Final query prepared is as following %+v", string(jsonString)))

    ctx := context.Background()
    conn, err := utils.GetMongoConnection()
    if err != nil {
        logrus.Errorf("Error connecting to mongo %+v", err)
        return result, err
    }
    logrus.Info("clientName %+v", clientName)

    // 使用正确的Pipeline参数执行聚合
    resultData, err := conn.Database(clientName).Collection("apnSummary").Aggregate(ctx, fullquery)
    if err != nil {
        logrus.Errorf("Error querying %+v", err)
        return result, err
    }

    mongodata := []utils.MonogResponse{}
    // 新增解码错误检查,避免忽略异常
    if err := resultData.All(ctx, &mongodata); err != nil {
        logrus.Errorf("Error decoding data %+v", err)
        return result, err
    }
    fmt.Println(mongodata)
    result = PrepareMongoResponse(mongodata)
    return result, nil
}

额外优化点

  • 移除了convertToInt函数,直接使用传入的字符串MessageId,确保与MongoDB中mid字段类型一致(若mid实际为整数类型,可恢复转换逻辑)。
  • 添加了resultData.All方法的错误检查,避免忽略数据解码过程中的异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.23 10:15:36