基于用户权限的分页产品获取MongoDB聚合实现需求
获取用户有权限的分页产品功能实现
目前已通过对PersonaEntityPermissionMapModel执行以下聚合查询,获取到用户(及所属用户组)有权限的产品/产品组数据:
PersonaEntityPermissionMapModel.aggregate([ { $match: { $or: [ { personaType: 'User', persona: user._id, entityType: { $in: ['MasterProduct', 'MasterProductGroup'], }, }, { personaType: 'UserGroup', persona: { $in: userGroupIds }, entityType: { $in: ['MasterProduct', 'MasterProductGroup'], }, }, ], }, }, { $project: { _id: 0, entityType: 1, entity: 1, action: 1, actionType: 1, }, }, ])
查询返回的数据结构如下:
const mappings = [ { entity: new ObjectId("63c5571347e5088b199f66b8"), entityType: 'MasterProduct', action: new ObjectId("63c5571347e5088b199f66ca"), actionType: 'Permission' }, { entity: new ObjectId("63c5571347e5088b199f66c5"), entityType: 'MasterProduct', action: new ObjectId("63c5571347e5088b199f66ca"), actionType: 'PermissionGroup' }, { entity: new ObjectId("63c5571347e5088b199f66cb"), entityType: 'MasterProductGroup', action: new ObjectId("63c5571347e5088b199f66ca"), actionType: 'Permission' }, { entity: new ObjectId("63c5571347e5088b199f66cc"), entityType: 'MasterProductGroup', action: new ObjectId("63c539640253848e04ff8d7a"), actionType: 'PermissionGroup' } ]
其中entityType对应集合为masterproducts/masterproductgroups,actionType对应集合为permissions/permissiongroups。需完成以下步骤实现最终需求:
- 从
masterproductgroups中获取所有关联的masterproducts - 为每个来自产品组的
masterproduct生成包含对应action和actionType的独立条目 - 按
masterproduct的ID分组,收集该产品所有唯一的Permission和PermissionGroup - 添加分页处理逻辑
- 关联填充
masterproducts集合中的产品详情信息 - 根据
actionType关联填充Permissions/PermissionGroups数据并合并到产品条目
完整聚合查询实现
PersonaEntityPermissionMapModel.aggregate([ // 筛选用户及所属组的产品/产品组权限映射 { $match: { $or: [ { personaType: 'User', persona: user._id, entityType: { $in: ['MasterProduct', 'MasterProductGroup'] } }, { personaType: 'UserGroup', persona: { $in: userGroupIds }, entityType: { $in: ['MasterProduct', 'MasterProductGroup'] } } ] } }, // 步骤1:关联查询产品组对应的所有产品 { $lookup: { from: 'masterproductgroups', localField: 'entity', foreignField: '_id', as: 'productGroup', pipeline: [ { $lookup: { from: 'masterproducts', localField: 'products', foreignField: '_id', as: 'products' } }, { $project: { products: 1 } } ] } }, // 步骤2:拆分产品组的产品为独立条目,保留直接关联的产品条目 { $set: { products: { $cond: { if: { $eq: ['$entityType', 'MasterProductGroup'] }, then: '$productGroup.products', else: [{ _id: '$entity' }] } } } }, { $unwind: '$products' }, { $project: { productId: '$products._id', action: 1, actionType: 1 } }, // 步骤3:按产品ID分组,收集唯一的权限/权限组 { $group: { _id: '$productId', permissions: { $addToSet: { $cond: [{ $eq: ['$actionType', 'Permission'] }, '$action', '$$REMOVE'] } }, permissionGroups: { $addToSet: { $cond: [{ $eq: ['$actionType', 'PermissionGroup'] }, '$action', '$$REMOVE'] } } } }, { $set: { permissions: { $filter: { input: '$permissions', cond: { $ne: ['$$this', '$$REMOVE'] } } }, permissionGroups: { $filter: { input: '$permissionGroups', cond: { $ne: ['$$this', '$$REMOVE'] } } } } }, // 步骤4:分页处理(page为当前页码,pageSize为每页数量) { $skip: (page - 1) * pageSize }, { $limit: pageSize }, // 步骤5:关联填充产品详情 { $lookup: { from: 'masterproducts', localField: '_id', foreignField: '_id', as: 'product', pipeline: [{ $project: { _id: 1, name: 1, description: 1 /* 按需选择字段 */ } }] } }, { $unwind: '$product' }, // 步骤6:关联填充权限和权限组数据并合并 { $lookup: { from: 'permissions', localField: 'permissions', foreignField: '_id', as: 'permissionDetails' } }, { $lookup: { from: 'permissiongroups', localField: 'permissionGroups', foreignField: '_id', as: 'permissionGroupDetails' } }, { $project: { _id: 0, product: '$product', allPermissions: { $concatArrays: ['$permissionDetails', '$permissionGroupDetails'] } } } ])
关键逻辑说明
- 产品组转产品:通过嵌套
$lookup获取产品组关联的所有产品,再用$unwind将每个产品拆分为独立条目,与直接关联的产品条目统一格式 - 权限去重:使用
$addToSet收集每个产品的唯一权限/权限组,再通过$filter移除无效值 - 分页:通过
$skip和$limit实现分页,需传入page和pageSize参数 - 数据填充:依次关联产品详情、权限详情、权限组详情,最后合并为统一的权限列表
内容的提问来源于stack exchange,提问作者shubham
相关产品推荐
相关产品推荐

