MongoDB 4.2聚合判断_id是否在关联子数组内失效问题
问题根因
你的聚合管道$addFields阶段判断逻辑存在两处问题,导致始终无法得到预期结果:
- 数组层级错误:
$lookup返回的join是关联到的User文档数组,直接引用$join.favorite得到的是二维数组,结构类似[ [id1, id2], [id3, id4] ],每个元素是单个User文档的favorite子数组。而$in聚合操作符仅支持在一维数组中检索元素,无法穿透嵌套层级匹配,因此永远返回false。 - 冗余判断:你当前的
$lookup关联规则本身就是localField: _id匹配foreignField: favorite,MongoDB处理数组类型的外键时,只要外键数组中存在和localField相等的值,就会将对应文档加入join结果集,因此join数组非空本身就已经代表当前Product的_id存在于关联User的favorite数组中,不需要额外遍历子数组判断。
修复代码
方案1(性能最优,兼容MongoDB 3.2及以上版本,完全适配4.2环境)
直接判断join数组长度即可,不需要做数组展开操作,执行效率最高:
db.Product.aggregate([ { $match: { $or: [ { "message": { $regex: "he" } }, { "field3": { $regex: "s" } } ] } }, { $lookup: { from: "User", localField: "_id", foreignField: "favorite", as: "join" } }, { $addFields: { favorited: { $gt: [ { $size: "$join" }, 0 ] } } } ])
方案2(适配后续lookup逻辑调整场景,兼容MongoDB 4.2)
如果后续修改了$lookup关联规则,确实需要手动校验_id是否存在于join子文档的favorite数组中,可以使用$reduce将二维数组展开为一维数组后再做匹配,不需要依赖4.4版本才支持的$function:
db.Product.aggregate([ { $match: { $or: [ { "message": { $regex: "he" } }, { "field3": { $regex: "s" } } ] } }, { $lookup: { from: "User", localField: "_id", foreignField: "favorite", as: "join" } }, { $addFields: { favorited: { $cond: [ { $in: [ "$_id", { $reduce: { input: "$join.favorite", initialValue: [], in: { $concatArrays: [ "$$value", "$$this" ] } } } ] }, true, false ] } } } ])
以上两种方案返回的结果完全匹配你给出的预期输出结构。
内容的提问来源于stack exchange,提问作者user11092881
相关产品推荐
相关产品推荐

