在MongoDB中处理"用户-角色"关系

本文涉及的产品
云数据库 MongoDB,通用型 2核4GB
简介: 一个简单的用户-角色-角色数据三者之间关系的MODEL设计的前后两种方式.前者用到了引用,后者用的是嵌套.象这种用户-角色的话,用嵌套更适合.毕竟一个用户的角色数据通常都不多.

假设我在设计一个有 用户-角色 关系的系统
受长久以来的关系数据库的经验影响,一开始我的设计是这样的.

const UserSchema = new Schema(
  {
    username: { type: String, require: true, unique: true },
    password: { type: String, require: true },
    nickName: String,
  },
);
UserSchema.virtual('roles', {
  ref: 'UserRole',
  localField: '_id',
  foreignField: 'user',
});

//UserSchema中定义了一个roles的虚拟键,
//收集UserRole集合中字段user与之相等的记录,
//即得到所有的角色

const UserRoleSchema = new Schema(
  {
    user: { type: Schema.Types.ObjectId, ref: 'User' },
    role: { type: Schema.Types.String, index: true, require: true },
    roleData: { type: Schema.Types.ObjectId, refPath: 'role' },
    createTime: { type: Date, default: new Date() },
    status: Number,
  }
);

//UserRole中的Role是一个字符串,
//其值为类似Admin,Teacher,Student这样的具体类型
//这些具体角色,即意味着有单独的集合存储
//roleData即指向那些具体的集合中的记录
//通过refPath指向role的值,一种动态的引用

const AdminSchema = new Schema(
  {
    user: { type: 'ObjectId', ref: 'User' },
    adminProp:String
  },
);

//Admin中就是存放与这类型角色有关的字段,

我的思路是尽量通过引用和populate方法来实现自动的数据引用更新. 比如我如果想移除一个用户的角色,我只需要删除UserRole集合中对应数据,在userModel.populate('roles')的时候就会得到更新后的结果.
另外,因为不同角色类型,字段不一样,我又希望使用明确键定义的Schema(方便数据校验).因此在UserRole中通过refPath做了动态引用.

虽然上边的设计能正常工作,不过呢,确实产生了好几个不同的集合.User,UserRole,Admin,Teacher,Student...

如果不考虑'强Schema',按照mongodb的设计理念来说,总感觉象我这里的用户与角色应该用嵌入的方式直接塞到User下边

调整如下

const UserSchema = new Schema(
  {
    username: { type: String, require: true, unique: true },
    password: { type: String, require: true },
    nickName: String,
    roles: { type: [UserRoleSchema], default: [] },
  },
}
//直接定义成数组子文档嵌套的方式

const UserRoleSchema = new Schema(
  {
    role: { type: Schema.Types.String, index: true, require: true },
    roleData: Schema.Types.Mixed, 
    createTime: { type: Date, default: new Date() },
    status: Number,
  }
}
//UserRoleSchema这个子文档定义里,
//去掉了原本用于关联User集合的user字段,
//roleData也从原来的引用到具体角色的类型变成了混合类,
//以方便直接插入各种类型角色数据

const AdminSchema = new Schema(
  {
    adminProp:String
  },
  { _id: false },
);

//Admin定义中只是注意省掉没意义的_id

因此最后的一个用户文档变成

{
  "_id" : ObjectId("5de87d8de6399413683b6c13"),
  "createTime" : ISODate("2019-12-05T03:45:27.731Z"),
  "username" : "user_test",
  "password" : "pass_test",
  "roles" : [{
      "_id" : ObjectId("5de8a3b448dc3530c8ebc64e"),
      "role" : "Admin",
      "roleData" : {
          "adminProp":"test",
      },
      "createTime" : ISODate("2019-12-05T06:29:07.465Z")
    }]
}

对比前后两种方式.前者用到了引用,后者用的是嵌套.象这种用户-角色的话,用嵌套更适合.毕竟一个用户的角色数据通常都不多.
这样设计更符合MongoDB的MODEL设计思想.而且最后就只需要一个USER集合,也没有populate vituals.更简洁了些
不知道大家怎么看?

最后参考一下这个链接
https://coderwall.com/p/px3c7g/mongodb-schema-design-embedded-vs-references

相关实践学习
MongoDB数据库入门
MongoDB数据库入门实验。
快速掌握 MongoDB 数据库
本课程主要讲解MongoDB数据库的基本知识,包括MongoDB数据库的安装、配置、服务的启动、数据的CRUD操作函数使用、MongoDB索引的使用(唯一索引、地理索引、过期索引、全文索引等)、MapReduce操作实现、用户管理、Java对MongoDB的操作支持(基于2.x驱动与3.x驱动的完全讲解)。 通过学习此课程,读者将具备MongoDB数据库的开发能力,并且能够使用MongoDB进行项目开发。   相关的阿里云产品:云数据库 MongoDB版 云数据库MongoDB版支持ReplicaSet和Sharding两种部署架构,具备安全审计,时间点备份等多项企业能力。在互联网、物联网、游戏、金融等领域被广泛采用。 云数据库MongoDB版(ApsaraDB for MongoDB)完全兼容MongoDB协议,基于飞天分布式系统和高可靠存储引擎,提供多节点高可用架构、弹性扩容、容灾、备份回滚、性能优化等解决方案。 产品详情: https://www.aliyun.com/product/mongodb
目录
相关文章
|
NoSQL 安全 MongoDB
mongodb设置用户账号密码登录
今天有个同事的项目中mongodb 被黑客攻占了,然后数据库被清掉,留下了一堆“案发现场”,还整了一个段话,附上给大家伙瞧瞧。。。。
573 1
mongodb设置用户账号密码登录
|
存储 监控 NoSQL
🍃MongoDB结合Koa2做用户登录验证
🍃MongoDB结合Koa2做用户登录验证
198 0
🍃MongoDB结合Koa2做用户登录验证
|
SQL 存储 NoSQL
MongoDB 在 2022 MongoDB 全球用户大会上发布新愿景,致力成为开发者数据平台提供商
引入一套统一的新功能,以满足开发者在构建现代应用程序方面日益增长的数据需求
MongoDB 在 2022 MongoDB 全球用户大会上发布新愿景,致力成为开发者数据平台提供商
|
NoSQL MongoDB 数据库
MongoDB 用户角色管理
MongoDB 服务默认是没有账号密码的,客户端连接上即可进行各种操作。如果在配置文件中,指定了auth=true,即开启了认证,那么客户端连接后需要认证才能执行操作。
MongoDB 用户角色管理
|
NoSQL 关系型数据库 数据库
MongoDB非关系型数据库的简介、创建数据库和表、配置用户等
简介: MongoDB是一个高性能,开源,无模式的文档型数据库,是一个基于分布式文件存储的数据库,是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的,是当前NoSQL数据库产品中最热门的一种。
1095 0