You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于用户权限的分页产品获取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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 06:20:23