MongoDB聚合$lookup阶段匹配结果错误,请求排查原因
MongoDB $lookup匹配错误问题排查
问题描述
在MongoDB聚合查询的$lookup阶段得到错误的匹配结果,当前返回两条记录,但预期仅返回一条符合条件的记录。
集合结构
// collection1 [ { _id: ObjectId("67bf2c061d02c9e2f7978905"), "pos_v": 111, "ref_v": "a", "alt_v": "b", "gf": 0.2 }, { _id: ObjectId("67bf2c061d02c9e2f7978908"), "pos_v": 222, "ref_v": "a", "alt_v": "d", "gf_v": 0.145 } ] // collection2 [ { "pos": 111, "ref": "a", "alt": "b", "fieldx": "hdhdhfh" }, { "pos": 324, "ref": "a", "alt": "s", "fieldx": "ssdf" } ]
执行的查询语句
db.collection1.aggregate([ { $match: { _id: ObjectId("67bf2c061d02c9e2f7978905") } }, { $lookup: { from: "collection2", let: { "pos_gv": "$pos", "ref_gv": "$ref", "alt_gv": "$alt" }, pipeline: [ { $match: { $expr: { $and: [ { $eq: [ "$$pos_gv", "$pos_v" ] }, { $eq: [ "$$ref_gv", "$ref_v" ] }, { $eq: [ "$$alt_gv", "$alt_v" ] } ] } } } ], as: "existingVariant" } }, { "$unwind": "$existingVariant" } ])
当前返回结果
[ { "_id": ObjectId("67bf2c061d02c9e2f7978905"), "alt_v": "b", "existingVariant": { "_id": ObjectId("5a934e000102030405000002"), "alt": "b", "fieldx": "hdhdhfh", "pos": 111, "ref": "a" }, "gf": 0.2, "pos_v": 111, "ref_v": "a" }, { "_id": ObjectId("67bf2c061d02c9e2f7978905"), "alt_v": "b", "existingVariant": { "_id": ObjectId("5a934e000102030405000003"), "alt": "s", "fieldx": "ssdf", "pos": 324, "ref": "a" }, "gf": 0.2, "pos_v": 111, "ref_v": "a" } ]
预期结果
[ { "_id": ObjectId("67bf2c061d02c9e2f7978905"), "alt_v": "b", "existingVariant": { "_id": ObjectId("5a934e000102030405000002"), "alt": "b", "fieldx": "hdhdhfh", "pos": 111, "ref": "a" }, "gf": 0.2, "pos_v": 111, "ref_v": "a" } ]
错误原因分析
查询出现错误匹配有两个核心问题:
- 变量引用错误:
let中定义的$pos、$ref、$alt并非collection1的字段(实际字段是pos_v、ref_v、alt_v),导致这些变量值均为null。 - 匹配字段反向:
$lookup的子管道中,错误地用collection2中不存在的$pos_v、$ref_v、$alt_v字段去匹配变量,而collection2的实际字段是pos、ref、alt。
由于null与null比较结果为true,导致collection2中所有文档都被匹配,最终返回两条记录。
修正后的查询语句
db.collection1.aggregate([ { $match: { _id: ObjectId("67bf2c061d02c9e2f7978905") } }, { $lookup: { from: "collection2", let: { // 正确引用collection1的字段 "pos_gv": "$pos_v", "ref_gv": "$ref_v", "alt_gv": "$alt_v" }, pipeline: [ { $match: { $expr: { $and: [ // 用collection2的字段匹配变量 { $eq: ["$pos", "$$pos_gv"] }, { $eq: ["$ref", "$$ref_gv"] }, { $eq: ["$alt", "$$alt_gv"] } ] } } } ], as: "existingVariant" } }, { "$unwind": "$existingVariant" } ])
内容的提问来源于stack exchange,提问作者Shahan
相关产品推荐
相关产品推荐

