MongoDB聚合管道中如何引用$match阶段的文档ID进行匹配?
解决MongoDB $lookup子Pipeline引用外部文档ID的问题
你的问题核心在于:$lookup内部pipeline中直接使用'$_id'会指向子集合(products)的文档ID,而非外部主集合的文档ID,导致匹配逻辑失效。以下是两种正确的实现方式:
方式一:通过let定义变量并引用
使用let将外部文档的_id定义为变量,再通过$$前缀引用该变量,同时用$expr包裹匹配逻辑(因为需要在$match中使用聚合表达式):
const aggregate = [ { $match: { mainCatId: new ObjectId(catId), }, }, { "$lookup": { "from": "products", "let": { "parentDocId": "$_id" }, // 将外部文档的_id赋值给变量parentDocId "pipeline": [ { "$match": { "$expr": { "$eq": [ "$subCategory", "$$parentDocId" ] } // 用$$引用变量,匹配subCategory与外部_id } }, ], "as": "products" } }, { "$unwind": "$products" } ];
方式二:直接引用$$ROOT
$$ROOT代表外部主集合的当前文档,可以直接通过$$ROOT._id获取其ID:
const aggregate = [ { $match: { mainCatId: new ObjectId(catId), }, }, { "$lookup": { "from": "products", "pipeline": [ { "$match": { "$expr": { "$eq": [ "$subCategory", "$$ROOT._id" ] } // 直接引用外部文档的_id } }, ], "as": "products" } }, { "$unwind": "$products" } ];
关键说明
- 必须使用
$expr:在$match中涉及聚合变量(如$$开头的变量)或字段间比较时,需要用$expr包裹逻辑,否则MongoDB会将右侧值视为普通字面量,而非聚合表达式。 $$前缀:用于引用let中定义的变量或系统变量(如$$ROOT),区别于引用当前子集合字段的$前缀。
内容的提问来源于stack exchange,提问作者Dominik Hartl
相关产品推荐
相关产品推荐

