0

我是 mongodb 和 mongoose 的新手,我在 mongoose 文档中搜索的越多,我就越迷路。
说我有一个user它的name字段有值John, John 有两个roles:

  • 超级用户
  • 行政

这个 s 中的每一个role都有一些permissions

  • 超级用户
    • 添加问题
    • 编辑问题
    • 删除问题
  • 行政
    • 添加问题
    • 查看答案

如您所见,每个都有重复项role,我怎样才能在没有重复项的数组中获取用户JohnaddQuestion的权限(此示例中的重复项是),如下所示:

['addQuestion', 'editQuestion', 'removeQuestion', 'viewAnswer']

这是我的架构:

var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var deepPopulate = require('mongoose-deep-populate')(mongoose);

var UserSchema = new Schema({
    name: String,
    user_roles: [{
        type: Schema.ObjectId,
        ref: 'Role'
    }]
});

var RoleSchema = new Schema({
    name: String,
    permissions: [
        {
            type: Schema.ObjectId,
            ref: 'Permission'
        }
    ]
});

var PermissionSchema = new Schema({
    name: String
});


UserSchema.plugin(deepPopulate, {
    whitelist: ['user_roles.permissions']
});

var User = mongoose.model('User', UserSchema),
Role   = mongoose.model('Role', RoleSchema),
Permission = mongoose.model('Permission', PermissionSchema);

如您所见,我没有permissions数组中的权限名称,我有引用(ObjectIds)。

我只有一个userId来自网址。所以:

User.findById(userId)
    .deepPopulate('user_roles')  
    .deepPopulate('user_roles.permissions') 
    .distinct('permissions') 
    .distinct('user_roles.permissions') 
    .exec((err, user)=> {
        if(err) res.send(err);
        ????
        res.json(permissionsArr);
    });

我应该使用distinct吗?我可以distinctpopulate先使用 ing 吗?还是必须的?或者distinct我应该使用user传入回调的项目而不是????使用user参数(使用find方法)来获取所有角色,并为所有角色获取权限,然后从permissionsArr数组中删除重复项?

更新:这是我使用猫鼬制作的休息 api 的结果,获取用户角色(GET http://localhost/api/users/:userId/roles):

app.get('/api/users/:userId/roles', function(req,res) {
    User.findById( req.params.userId )
        .deepPopulate('user_roles.permissions')
        .select('user_roles')
        .exec((err, users)=> {
            if(err) next(err);
            res.json(users);
        });
}

结果:

{
  "name": "John",
  "_id": "56e677c1a7e7007d5cc245ef",
  "user_roles": [
      {
          "_id": "56e64f057e8008263dec2cc9",
          "name": "superuser",
          "permissions": [
              {
                  "name": "removeQuestion",
                  "_id": "56e408a9d863a8cf4d7ab001"
              },
              {
                  "name": "addQuestion",
                  "_id": "56e64d657e8008263dec2cc4"
             },
             {
                  "name": "addAnswer",
                  "_id": "56e64cf87e8008263dec2cc3"
             },
             {
                  "name": "viewQuestion",
                  "_id": "56e64e1e7e8008263dec2cc5"
             },
             {
                  "name": "viewAnswer",
                  "_id": "56e64e267e8008263dec2cc6"
             }
          ]
    },
    {
          "_id": "56e64ec27e8008263dec2cc8",
          "name": "admin",
          "permissions": [ 
              {
                  "name": "addQuestion",
                  "_id": "56e64d657e8008263dec2cc4"
              },
              {
                  "name": "addAnswer",
                  "_id": "56e64cf87e8008263dec2cc3"
              },
              {
                  "name": "viewQuestion",
                  "_id": "56e64e1e7e8008263dec2cc5"
              },
              {
                  "name": "viewAnswer",
                  "_id": "56e64e267e8008263dec2cc6"
              }
          ]
        }

现在我需要的是GET http://localhost/api/users/:userId/permissions并通过它获取用户拥有的,但重复项已被删除。(permissions不应该直接。)rolesuserpermissions

感谢您抽出宝贵的时间以及您能够提供的任何帮助。

4

2 回答 2

1

在使用您的架构测试了一些代码后,我发现.distinct只是不同的值user_roles而不是 的结果populate,例如user_roles.permissions. permissions这可能是通过过滤用户结果填充后删除重复项的一种方法。

User.findById('56e7b1f74e7192381adbfdbc')
    .populate({
        path: 'user_roles',
        model: 'Role',
        populate: {
            path: 'permissions',
            model: 'Permission'         
        }
    })
    .exec(function(err, user) {
        if (err)
            console.log(err);
        else {
            //console.log(util.inspect(user, { showHidden: true, depth: null }));

            var s = new Set();
            // remove duplicate permission 
            user.user_roles.forEach(function(u){
                u.permissions.forEach(function(p) {
                    s.add(p.name);
                })
            })

            var arr = [...s]; // convert set to array
            console.log(arr);
        }
    });

顺便说一句,您可以在不使用模块的情况下以这种方式嵌套填充结果mongoose-deep-populate

于 2016-03-15T09:00:42.950 回答
0

实际上,您可以使用聚合框架对嵌套的权限数组进行重复数据删除。您还可以选择 map-reduce,但建议使用聚合框架,并且性能更高。

db.users.aggregate([
    {$match:{_id:"56e677c1a7e7007d5cc245ef"}},
    {$unwind:"$user_roles"},
    {$unwind:"$user_roles.permissions"},
    {$group:{_id:"$_id", permissions:{$addToSet:"$user_roles.permissions.name"}}}
])

根据您的示例文档,它应该获取

{ 
    "_id" : "56e677c1a7e7007d5cc245ef", 
    "permissions" : [
        "addAnswer", 
        "viewAnswer", 
        "viewQuestion", 
        "addQuestion", 
        "removeQuestion"
    ]
}

我很肯定你可以把它翻译成猫鼬,这很容易。

于 2016-03-15T12:24:07.130 回答