MongoDB聚合查询:筛选双属性组合下仅存失败记录的条目并按发送方分组
核心问题定位
你当前的查询逻辑存在本质设计漏洞:聚合管道第一步就执行了{ $match: { success: false } },直接把所有成功请求的记录从后续流程中剔除,根本无法完成「校验指定sender+domainID组合是否存在历史成功记录」的核心逻辑。比如示例数据里sender=6、domainID=AAA的组合本来存在1条成功记录,但被提前过滤后,剩下的1条失败记录会被错误纳入结果,完全不符合筛选要求。
可直接运行的实现方案
核心实现思路是先按sender+domainID的复合维度做第一阶段分组,完成状态校验,再按sender维度做二次分组汇总结果,完整聚合代码如下:
const pendingWebhooks = await WebhooksCollection.aggregate([ // 第一阶段:按 sender + domainID 复合维度分组,统计每个组合的历史状态 { $group: { _id: { sender: "$sender", domainID: "$domainID" }, // 标记该组合是否存在过成功请求:只要有1条成功记录值就为1,全失败则为0 hasAnySuccessRecord: { $max: { $cond: [{ $eq: ["$success", true] }, 1, 0] } }, // 收集该组合下所有失败请求的内容,成功记录不纳入 failedRequestList: { $push: { $cond: [ { $eq: ["$success", false] }, { content: "$content" }, "$$REMOVE" ] } } } }, // 第二阶段:过滤出从未产生过成功请求的组合 { $match: { hasAnySuccessRecord: 0 } }, // 第三阶段:按sender维度二次分组,汇总该发送方下所有符合要求的待处理请求 { $group: { _id: "$_id.sender", rawPendingRequests: { $push: "$failedRequestList" } } }, // 第四阶段:展平数组结构,避免出现嵌套二维数组 { $set: { pendingRequests: { $reduce: { input: "$rawPendingRequests", initialValue: [], in: { $concatArrays: ["$$value", "$$this"] } } }, rawPendingRequests: "$$REMOVE" } } ]);
结果匹配校验
用你提供的示例数据运行上述查询,输出结果和预期完全一致:
- sender=6 + domainID=AAA的组合:存在1条成功记录,被直接过滤,不纳入结果
- sender=7 + domainID=CCC的组合:全为成功记录,无失败请求内容,被过滤
- sender=8 + domainID=CCC的组合:无任何成功历史记录,仅存1条失败请求,最终被纳入结果,输出结构和你给出的预期返回完全匹配。
内容的提问来源于stack exchange,提问作者Luis Pinto
相关产品推荐
相关产品推荐

