MongoDB分组聚合结果过滤优化:无需$unwind获取匹配角色
高效解决方案(无需$unwind)
核心思路是在单文档层面先过滤出匹配目标组织的权限条目,再基于该条目进行分组,避免$unwind带来的文档膨胀问题。
最终聚合语句
[ { "$match": { "accessControl.organization": ObjectId("64591e18c826eb8dec7cff39") } }, { "$addFields": { "matchedAccess": { "$filter": { "input": "$accessControl", "as": "ac", "cond": { "$eq": ["$$ac.organization", ObjectId("64591e18c826eb8dec7cff39")] } } } } }, { "$group": { "_id": { "roleName": { "$arrayElemAt": ["$matchedAccess.role.name", 0] }, "roleId": { "$arrayElemAt": ["$matchedAccess.role._id", 0] } }, "users": { "$push": { "_id": "$_id", "disabled": "$disabled", "email": "$email", "emailVerified": "$emailVerified", "name": "$name", "accessControl": "$matchedAccess" } } } }, { "$project": { "_id": 0, "role": { "name": "$_id.roleName", "id": "$_id.roleId" }, "users": 1 } } ]
关键步骤说明
- $match阶段:和原语句一致,快速筛选出包含目标组织权限的用户,可利用
accessControl.organization字段的索引提升查询效率。 - $addFields阶段:用
$filter遍历accessControl数组,仅保留与目标组织匹配的权限条目,存入matchedAccess字段。这一步在单文档内完成数组过滤,不会产生额外文档。 - $group阶段:基于
matchedAccess中的角色信息分组,用$arrayElemAt取数组第一个元素(假设单个用户在同一组织下仅对应一个权限条目),避免因数组导致的分组混乱;同时将用户信息推入对应角色的users数组,且仅保留匹配组织的权限。 - $project阶段:调整输出格式,将分组ID转换为清晰的
role结构,去除冗余字段。
效率优势
相比$unwind会将每个数组条目拆分为独立文档(数据量可能成倍数膨胀),此方案通过单文档内的数组操作完成筛选,大幅减少中间处理的文档数量,在大数据量场景下性能提升明显。
内容的提问来源于stack exchange,提问作者Diego L
相关产品推荐
相关产品推荐

