MongoDB聚合$lookup关联后如何过滤listCard数组中status非1的元素
问题原因
你现有的写法中,$match阶段的"listCard.status":{$eq : ACTIVE_STATUS}作用是过滤父文档,仅保留listCard数组中至少存在一个符合status条件的父集合文档,并不会对listCard数组内部的元素做筛选。
解决方案
提供两种可落地的实现方式:
方案1:在$lookup阶段直接过滤关联数据(推荐,性能更优)
直接在关联阶段就过滤掉子集合不符合条件的文档,减少不必要的数据加载:
// 先过滤父集合符合条件的文档,提前缩小范围提升性能 pipeline.push( { $match: { status: {$eq: ACTIVE_STATUS} } }, { $lookup: { from: "listCard", let: { taskListId: "$_id" }, pipeline: [ { $match: { $expr: { $eq: ["$taskListId", "$$taskListId"] }, status: {$eq: ACTIVE_STATUS} } } ], as: "listCard" } } ); // 原有投影逻辑不需要修改 let projection = { projectId : 1, title: 1, sortOrder : 1, status : 1, listCard : 1, }
方案2:$lookup之后使用$filter过滤数组
如果你不想修改原有$lookup逻辑,也可以在关联后新增阶段过滤listCard数组:
pipeline.push( { $lookup: { from: "listCard", localField: "_id", foreignField: "taskListId", as: "listCard" } }, { $match: { status: {$eq: ACTIVE_STATUS}, "listCard.status":{$eq : ACTIVE_STATUS} } }, // 新增阶段过滤数组内部元素 { $addFields: { listCard: { $filter: { input: "$listCard", cond: { $eq: ["$$this.status", ACTIVE_STATUS] } } } } } );
$addFields会保留原有所有字段,仅更新listCard字段为过滤后的结果,不需要修改原有投影逻辑。
内容的提问来源于stack exchange,提问作者Ezad Abada
相关产品推荐
相关产品推荐

