如何通过Mongo Aggregation实现指定条件的文档筛选?
MongoDB聚合筛选用户角色记录的正确实现
需求规则
- 若用户存在
active: true的manager角色记录,仅保留该用户的manager记录,忽略所有user角色记录 - 若用户的
manager角色记录active: false,保留该用户所有user角色记录(无论user的active状态) - 若用户无
manager角色记录,保留其所有user角色记录;反之,无user记录则保留manager记录
示例数据集
[ { role:"manager", user:"john", active:true }, { role:"user", region:"us", user:"john", active:false }, { role:"user", region:"czk", user:"john", active:false }, { role:"user", region:"czk", user:"jane", active:false }, { role:"user", region:"us", user:"jane", active:true }, { role:"manager", user:"jane", active:false } ]
预期结果
获取索引0、3、4的文档,即:
[ { role:"manager", user:"john", active:true }, { role:"user", region:"czk", user:"jane", active:false }, { role:"user", region:"us", user:"jane", active:true } ]
原方案问题
原聚合语句仅筛选active: true的manager和user记录,完全不符合需求逻辑——既无法处理用户存在active: false的manager时需保留所有user的情况,也未对用户的角色关联关系做判断。
正确聚合实现
我们需要先按用户分组,判断每个用户的角色状态,再根据规则筛选记录:
db.collection.aggregate([ // 1. 按用户分组,收集所有记录并标记是否存在激活的manager { $group: { _id: "$user", records: { $push: "$$ROOT" }, hasActiveManager: { $max: { $cond: [{ $and: [{ $eq: ["$role", "manager"] }, { $eq: ["$active", true] }] }, true, false] } } } }, // 2. 根据分组标记筛选符合规则的记录 { $project: { filteredRecords: { $filter: { input: "$records", as: "record", cond: { $switch: { branches: [ // 情况1:存在激活的manager,仅保留manager记录 { case: "$hasActiveManager", then: { $eq: ["$$record.role", "manager"] } }, // 情况2:无激活manager,保留所有user记录;若用户只有一条manager记录(active:false)也保留 { case: { $not: "$hasActiveManager" }, then: { $or: [ { $eq: ["$$record.role", "user"] }, { $and: [{ $eq: ["$$record.role", "manager"] }, { $eq: [{ $size: "$records" }, 1] }] } ] } } ], default: false } } } } } }, // 3. 展开筛选后的记录数组 { $unwind: "$filteredRecords" }, // 4. 恢复原文档结构 { $replaceRoot: { newRoot: "$filteredRecords" } } ])
逻辑说明
- 分组阶段:按用户聚合,收集该用户的所有记录,同时用
$max和$cond判断是否存在激活的manager角色 - 筛选阶段:用
$switch分情况处理规则:- 存在激活manager时,仅保留该用户的manager记录
- 无激活manager时,保留所有user记录;若用户只有一条
active: false的manager记录,也保留该记录
- 展开与替换根:将筛选后的数组展开,恢复为原文档格式
内容的提问来源于stack exchange,提问作者Abbas Shaikh
相关产品推荐
相关产品推荐

