在MongoDB中插入时如何检查引用?

时间:2015-09-13 05:52:27

标签: mongodb

假设我有用户和角色。每个用户都属于一个角色。我想像这样设计数据库:

收集用户:

{
    "name":"user1"
    "role":"admin"
}

收集角色:

{
    "name":"admin"
    "privileges":[]
}
{
    "name":"user"
    "privileges":[]
}

稍后我可以为任何角色添加更多角色或编辑权限。

我的问题是:当我插入新用户时,如何检查“角色”字段是否具有有效值(这意味着角色集合中有匹配文档)?

我应该在申请表中查看此参考资料吗?有没有办法在mongodb服务器端这样做?

我们假设编辑权限是一种常见的操作。

2 个答案:

答案 0 :(得分:1)

由于您免费获得_id的索引,因此您应该将用户引用到角色_id

{
    _id: ObjectId("55f5128e6e5daa295293e31e"),
    name: "admin"
},
{
    _id: ObjectId("55f5128e6e5daa295293e31f"),
    "name":"user"
}

并按用户分配权限

{
    "name":"user1",
    "role":ObjectId("55f5128e6e5daa295293e31e"),
    "privileges":[]
}

更好的是,摆脱角色集合

{
    "name":"user1",
    "role": "admin",
    "privileges":[]
}

{
    "name":"user1",
    "role": {
        "type": "admin",
        "additionaField": "value"
    },
    "privileges":[]
}

编辑:

Chris Ma"如果我有1k用户角色" admin"该怎么办?现在我想为所有管理员添加权限。然后我必须编辑1k用户。对?我们有更好的解决方案吗?"

如果可以想象,解决方案将是相同的:

收集"角色"

{
    _id: ObjectId("55f5128e6e5daa295293e31e"),
    name: "admin",
    my1KUpdate: "value"
}

答案 1 :(得分:1)

我认为你把车推到了马前。

对于数据建模,首先应该对数据提出什么问题。至于用户,角色和权限关系,问题很明显

  

对于给定用户,有哪些权限?

只要每个角色的权限不超过几个100k,您的角色模型应该相当简单

{
  _id: "roleName",
  description: "a role",
  privileges:[
      "someService:someAction:someInstance",
  ]
},
{
  _id: "admin",
  description: "Administrator",
  privileges:[
      "adminService:*:*",
  ]
}

我们有一个给定用户的简化模型

{
  _id: "foo",
  roles: ["roleName","admin"]
}

为了获得给定用户“foo”(您之前加载为user)的权限,我们执行类似

的操作
var user_privileges = db.roles.aggregate([
  { $match:{ _id:{ $in: user.roles} } },
  { $unwind: "$privileges" },
  { $group:{ _id: null, $push:{ "forAllRoles": "$privileges" } }
]}

应该产生像

这样的结果文档
{ _id: null, forAllRoles:[
    "adminService:*:*",  
    "someService:someAction:someInstance"
  ]
}

现在可以轻松检查权限

var permission_needed = "adminService:*:*"

if(user_privileges.forAllRoles.indexOf(permission_needed) > -1){
  console.log("Yay, admin!");
  doSomeAdminStuff();
} else {
  console.log("Don't you dare again, user!");
}

由于我们通过索引的roles._id查找权限,因此聚合应该非常有效,因为我们在处理之前将文档限制为非常少。

如果您想为角色添加权限,这很简单

db.roles.update(
  { _id: "roleName" },
  { $addToSet: { privileges: [ "otherService:*:someInstance" ] } }
)

HTH