Mongoose聚合$lookup能否使用多foreignField?Mongo3.4查询需求
嘿,针对你的两个MongoDB聚合问题,我来给你详细解答~
1. 仅获取xyz集合中flag为true的匹配结果
由于你使用的是MongoDB 3.4,这个版本的$lookup还不支持在关联阶段直接添加过滤条件的pipeline。所以我们可以先完成全量关联,再通过$addFields配合$filter来筛选出符合flag: true的文档:
Model.aggregate([ { $match: {} }, { $lookup:{ "from": "xyz", "localField": "_id", "foreignField": "xyzId", "as": "xyz" } }, { $addFields: { xyz: { $filter: { input: "$xyz", cond: { $eq: ["$$this.flag", true] } } } } } ])
执行这段聚合后,返回结果里的xyz数组就只会保留flag为true的匹配文档。如果没有符合条件的匹配项,xyz会是一个空数组。
2. $lookup中是否可以使用两个foreignField进行匹配?
在MongoDB 3.4版本中,原生的$lookup仅支持单字段的localField与foreignField关联。如果需要多字段匹配,有两种可行方案:
方案一:构造复合关联字段
提前在abc和xyz集合中,把需要关联的多个字段组合成一个复合字段(比如用$concat拼接字符串,或者自定义一个包含多字段信息的键),然后将这个复合字段作为localField和foreignField进行关联。这种方式适合无法升级MongoDB版本的场景。方案二:升级到MongoDB 3.6+使用带pipeline的$lookup
从MongoDB 3.6开始,$lookup支持传入自定义pipeline,这让多字段关联变得非常灵活。你可以在pipeline里用$match添加任意多的关联条件,甚至还能顺便完成flag的过滤,不用再单独加$filter阶段。举个例子(假设要同时匹配xyzId和name两个字段):
Model.aggregate([ { $match: {} }, { $lookup: { from: "xyz", let: { abcId: "$_id", abcName: "$name" }, // 定义局部变量引用abc集合的字段 pipeline: [ { $match: { $expr: { $and: [ { $eq: ["$xyzId", "$$abcId"] }, // 匹配xyzId { $eq: ["$name", "$$abcName"] } // 同时匹配name ] } } }, { $match: { flag: true } } // 直接在这里过滤flag为true的文档 ], as: "xyz" } } ])
这种方式不仅能实现多字段关联,还能减少后续的聚合阶段,提升查询效率。
内容的提问来源于stack exchange,提问作者Gunjan Patel
相关产品推荐
相关产品推荐

