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
相关产品推荐
相关产品推荐

