Nodejs mongoDB多对多关系,如何设计数据库?
Nodejs mongoDB多对多关系,如何设计数据库?
角色表,权限表,用户表,他们之间都是多对多的关系,在mongoDB中可以如何设计文档结构呢?
在MongoDB中处理多对多关系时,可以通过嵌套引用或使用独立的集合来管理关联。对于角色表、权限表和用户表之间的多对多关系,我们可以采用一种灵活的设计方法。以下是一个示例设计:
角色表(Roles)
每个角色可以拥有多个权限,并且一个权限可以被多个角色共享。
{
"_id": ObjectId("5f9c8d4b27a3e10e0c7f1d23"),
"name": "admin",
"permissions": [
{ "$ref": "permissions", "$id": ObjectId("5f9c8d4b27a3e10e0c7f1d24"), "$db": "mydatabase" },
{ "$ref": "permissions", "$id": ObjectId("5f9c8d4b27a3e10e0c7f1d25"), "$db": "mydatabase" }
]
}
权限表(Permissions)
每个权限可以被多个角色拥有。
{
"_id": ObjectId("5f9c8d4b27a3e10e0c7f1d24"),
"name": "view_users"
},
{
"_id": ObjectId("5f9c8d4b27a3e10e0c7f1d25"),
"name": "edit_users"
}
用户表(Users)
每个用户可以属于多个角色,并且一个角色可以包含多个用户。
{
"_id": ObjectId("5f9c8d4b27a3e10e0c7f1d26"),
"username": "john_doe",
"roles": [
{ "$ref": "roles", "$id": ObjectId("5f9c8d4b27a3e10e0c7f1d23"), "$db": "mydatabase" }
]
}
示例代码
添加权限到角色
const roleModel = mongoose.model('Role', roleSchema);
const permissionModel = mongoose.model('Permission', permissionSchema);
async function addPermissionToRole(roleId, permissionId) {
const role = await roleModel.findById(roleId);
role.permissions.push({
$ref: 'permissions',
$id: permissionId,
$db: 'mydatabase'
});
await role.save();
}
添加用户到角色
const userModel = mongoose.model('User', userSchema);
async function addUserToRole(userId, roleId) {
const user = await userModel.findById(userId);
user.roles.push({
$ref: 'roles',
$id: roleId,
$db: 'mydatabase'
});
await user.save();
}
解释
- 嵌套引用:我们通过
$ref
和$id
字段来引用其他集合中的文档。 - 查询优化:为了高效地获取用户的角色和权限信息,可以在应用层进行多次查询或使用聚合框架进行复杂查询。
- 数据一致性:由于MongoDB不支持事务,确保数据一致性的责任落在了应用程序层面。
这种方法既保持了灵活性,又能够有效地管理复杂的多对多关系。
这样写不知道你能不能明白。。。如果你会基本的查询应该想想就明白了。。。 users (hash) userid:1 roleA : 1 (set) add , edit , del
我想问的是具体的设计思路以及如何查询的问题,比如多对多可以用link,也可以用DBRef,还有就是单个文档大小限制的问题也需要考虑? 不知这个如何 https://www.npmjs.org/package/mongoose-relationship
在MongoDB中处理多对多关系通常可以通过嵌套引用或使用中间集合来实现。对于你的需求(角色、权限、用户之间的多对多关系),推荐使用中间集合的方法。
设计思路
-
用户表 (
users
)- 每个用户可能属于多个角色。
- 用户可以拥有多个权限,但这些权限是通过角色间接关联的。
-
角色表 (
roles
)- 每个角色可以包含多个权限。
- 每个角色可以分配给多个用户。
-
权限表 (
permissions
)- 权限是独立的实体,可以被多个角色共享。
-
中间集合 (
user_roles
和role_permissions
)user_roles
: 用于记录用户与角色的关系。role_permissions
: 用于记录角色与权限的关系。
示例设计
用户表 (users
)
{
"_id": ObjectId("650d9b1c123456789abcde"),
"name": "Alice",
"email": "alice@example.com"
}
角色表 (roles
)
{
"_id": ObjectId("650d9b1c123456789abcdf"),
"name": "Admin"
}
权限表 (permissions
)
{
"_id": ObjectId("650d9b1c123456789abcda"),
"name": "read"
}
中间集合: 用户角色 (user_roles
)
{
"_id": ObjectId("650d9b1c123456789abcdb"),
"userId": ObjectId("650d9b1c123456789abcde"),
"roleId": ObjectId("650d9b1c123456789abcdf")
}
中间集合: 角色权限 (role_permissions
)
{
"_id": ObjectId("650d9b1c123456789abcdd"),
"roleId": ObjectId("650d9b1c123456789abcdf"),
"permissionId": ObjectId("650d9b1c123456789abcda")
}
示例查询
查询用户 Alice 的所有权限:
const userId = ObjectId("650d9b1c123456789abcde");
db.user_roles.find({ userId }).toArray().map(userRole => {
return db.role_permissions.findOne({ roleId: userRole.roleId }).then(rolePermission => {
return db.permissions.findOne({ _id: rolePermission.permissionId });
});
}).then(permissions => {
console.log(permissions);
});
总结
这种设计方式通过两个中间集合将多对多关系解耦,既保留了灵活性,也方便了数据管理和查询。在实际应用中,可以根据业务需求调整字段和索引以优化性能。