如何用MongoDB聚合实现两步查询:匹配beginner类型Score值的所有记录
MongoDB聚合实现指定筛选需求的方案
需求说明
从集合中筛选出所有Score值曾在Type为beginner的文档中出现过的记录,排除那些Score仅在advanced类型文档中出现的条目(比如示例中的User E)。
聚合查询实现
可以通过以下聚合管道完成需求(记得将collection替换为你的实际集合名称):
db.collection.aggregate([ // 收集所有beginner类型的去重Score值 { $group: { _id: null, beginnerScores: { $addToSet: { $cond: [{ $eq: ["$Type", "beginner"] }, "$Score", "$$REMOVE"] } } } }, // 自关联匹配所有Score在目标列表中的文档 { $lookup: { from: "collection", let: { targetScores: "$beginnerScores" }, pipeline: [ { $match: { $expr: { $in: ["$Score", "$$targetScores"] } } } ], as: "matchedDocuments" } }, // 展开匹配到的文档数组 { $unwind: "$matchedDocuments" }, // 恢复原文档结构作为输出 { $replaceRoot: { newRoot: "$matchedDocuments" } } ])
步骤详解
- $group阶段:将全集合聚合为单个组,通过
$cond筛选出Type为beginner的文档的Score,用$addToSet去重后存入beginnerScores数组。 - $lookup阶段:执行自关联查询,以
beginnerScores为条件,匹配原集合中Score属于该数组的所有文档,结果存入matchedDocuments数组。 - $unwind阶段:将
matchedDocuments数组拆分为独立的文档条目。 - $replaceRoot阶段:把每个拆分后的文档设为根文档,输出与原数据结构一致的结果。
简化版(MongoDB 5.0+)
如果使用MongoDB 5.0及以上版本,可以借助窗口函数简化操作,无需自关联:
db.collection.aggregate([ // 给每个文档添加全集合的beginner Score列表 { $setWindowFields: { partitionBy: null, output: { beginnerScores: { $addToSet: { $cond: [{ $eq: ["$Type", "beginner"] }, "$Score", "$$REMOVE"] } } } } }, // 筛选Score在目标列表中的文档 { $match: { $expr: { $in: ["$Score", "$beginnerScores"] } } }, // 移除临时添加的字段 { $unset: "beginnerScores" } ])
内容的提问来源于stack exchange,提问作者Hagay r
相关产品推荐
相关产品推荐

