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

MongoDB Aggregation Lookup管道在Golang中返回错误数据问题

问题排查与修复方案

你的问题核心是MongoDB Compass中运行正常的MQL,转成Go代码后返回数组长度正确但数据不符。以下是几个关键排查点和修复建议:

1. $convert 错误处理值类型不匹配

在lookup pipeline的$convert阶段,onError设置为空字符串"",而$$inDateTime是通过$dateFromString生成的BSON日期类型。字符串与日期无法正确比较,会导致匹配逻辑失效。

修复:
将onError改为null或默认日期值,确保类型一致:

{"$convert", bson.D{
    {"input", "$start"},
    {"to", "date"},
    {"onError", nil}, // 改为null
}}

2. 使用bson.M替代部分bson.D以避免顺序问题

bson.D是有序文档,而MongoDB部分表达式对字段顺序不敏感,错误的顺序可能导致解析异常。对于不需要严格顺序的表达式,改用bson.M更灵活。

示例修改:
将$expr内的$and表达式改用bson.M:

{"$expr", bson.M{
    "$and": []interface{}{
        bson.M{"$eq": []interface{}{"$hubname", "$$ophubname"}},
        bson.M{"$gte": []interface{}{
            bson.M{"$convert": bson.M{
                "input": "$start",
                "to": "date",
                "onError": nil,
            }},
            "$$inDateTime",
        }},
        bson.M{"$lte": []interface{}{
            bson.M{"$convert": bson.M{
                "input": "$stop",
                "to": "date",
                "onError": primitive.NewDateTimeFromTime(time.Now()),
            }},
            "$$outDateTime",
        }},
    },
}}

3. 确保time.Now()正确转为BSON日期

在$cond的else分支中直接使用time.Now(),虽然驱动通常会自动转换,但显式转为BSON日期更稳妥:

{"$cond", bson.A{
    bson.D{{"$ne", bson.A{"$outdate", ""}}},
    // ... 原有逻辑 ...
    primitive.NewDateTimeFromTime(time.Now()), // 显式转换为BSON日期
}}

4. 简化$match条件(可选)

第一个$match中的$and可以简化,MongoDB会自动对多个条件执行AND操作:

{"$match", bson.D{
    {"start", bson.D{{"$exists", true}}},
    {"stop", bson.D{{"$exists", true}}},
    {"stop", bson.D{{"$ne", ""}}},
}}

完整修复后的代码片段

import (
    "context"
    "time"
    "go.mongodb.org/mongo-driver/bson"
    "go.mongodb.org/mongo-driver/bson/primitive"
    "go.mongodb.org/mongo-driver/mongo"
)

// ...

var query = mongo.Pipeline{
    {
        {"$addFields", bson.D{
            {"opStartDate", bson.D{
                {"$dateFromString", bson.D{
                    {"dateString", bson.D{
                        {"$concat", bson.A{"$indate", " ", "$intime"}},
                    }},
                    {"format", "%d-%m-%Y %H:%M:%S"},
                }},
            }},
            {"opEndDate", bson.D{
                {"$cond", bson.A{
                    bson.D{{"$ne", bson.A{"$outdate", ""}}},
                    bson.D{
                        {"$dateFromString", bson.D{
                            {"dateString", bson.D{
                                {"$concat", bson.A{"$outdate", " ", "$outtime"}},
                            }},
                            {"format", "%d-%m-%Y %H:%M:%S"},
                        }},
                    },
                    primitive.NewDateTimeFromTime(time.Now()),
                }},
            }},
        }},
    },
    {
        {"$lookup", bson.D{
            {"from", "transaction"},
            {"let", bson.D{
                {"ophubname", "$hubname"},
                {"inDateTime", "$opStartDate"},
                {"outDateTime", "$opEndDate"},
            }},
            {"pipeline", bson.A{
                {
                    {"$match", bson.D{
                        {"start", bson.D{{"$exists", true}}},
                        {"stop", bson.D{{"$exists", true}}},
                        {"stop", bson.D{{"$ne", ""}}},
                    }},
                },
                {
                    {"$match", bson.D{
                        {"$expr", bson.M{
                            "$and": []interface{}{
                                bson.M{"$eq": []interface{}{"$hubname", "$$ophubname"}},
                                bson.M{"$gte": []interface{}{
                                    bson.M{"$convert": bson.M{
                                        "input": "$start",
                                        "to": "date",
                                        "onError": nil,
                                    }},
                                    "$$inDateTime",
                                }},
                                bson.M{"$lte": []interface{}{
                                    bson.M{"$convert": bson.M{
                                        "input": "$stop",
                                        "to": "date",
                                        "onError": primitive.NewDateTimeFromTime(time.Now()),
                                    }},
                                    "$$outDateTime",
                                }},
                            },
                        }},
                    }},
                },
            }},
            {"as", "transaction"},
        }},
    },
}

cur, err := collection.Aggregate(context.TODO(), query)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 01:21:06