MongoDB聚合lookup后如何添加match筛选指定profile._id结果
MongoDB聚合查询匹配指定profile._id的解决方案
匹配不生效的核心原因
添加$match阶段未得到预期结果,通常是两个问题导致:
- 字段路径错误:
_id是嵌套在profile对象下的字段,匹配时需要写完整路径profile._id,直接写_id无法命中目标字段 - 类型不匹配:MongoDB中存储的文档
_id是ObjectId类型,直接传入普通字符串做相等匹配会因为类型不一致返回空结果
可行方案
方案1:在$unwind后添加$match阶段(改动最小)
在$unwind执行完成后、$project阶段前插入$match过滤,提前筛掉不符合要求的文档,减少后续阶段的数据处理量,修改后的完整聚合语句如下:
db.ministryteams.aggregate([ { $addFields: { "id_ministryTeam": { $toObjectId: "$_id" } } }, { $lookup: { from: "profiles", localField: "phone", foreignField: "phone", as: "profile" }, }, { $unwind: "$profile" }, // 新增匹配阶段 { $match: { "profile._id": ObjectId("62a798074e105c2b74fe6d81") } }, { $project: { "profile._id": 1, "profile.name": 1, "profile.phone": 1, "profile.type": 1, "profile.contactAllowed": 1, "profile.createAt": 1, "id_ministryTeam": 1, "_id": 0 } } ])
方案2:在$lookup阶段直接过滤关联数据(性能更优)
直接给$lookup加自定义聚合管道,关联查询时就只拉取符合_id要求的profile文档,不需要关联全量匹配手机号的profile再过滤,数据量大时性能提升明显,语句如下:
db.ministryteams.aggregate([ { $addFields: { "id_ministryTeam": { $toObjectId: "$_id" } } }, { $lookup: { from: "profiles", let: { refPhone: "$phone" }, pipeline: [ { $match: { $expr: { $and: [ { $eq: ["$phone", "$$refPhone"] }, { $eq: ["$_id", ObjectId("62a798074e105c2b74fe6d81")] } ] } } } ], as: "profile" }, }, { $unwind: "$profile" }, { $project: { "profile._id": 1, "profile.name": 1, "profile.phone": 1, "profile.type": 1, "profile.contactAllowed": 1, "profile.createAt": 1, "id_ministryTeam": 1, "_id": 0 } } ])
注意:如果你的执行环境不支持直接调用
ObjectId()构造方法,可以用聚合操作符做类型转换,匹配条件替换为"profile._id": { $toObjectId: "62a798074e105c2b74fe6d81" }即可,效果完全一致。
内容的提问来源于stack exchange,提问作者jeferson.mdca
相关产品推荐
相关产品推荐

