如何使用Mongoose关联MongoDB中的User和Role两个Schema?
Mongoose关联User和Role Schema的实现方案
以下是两种符合需求的实现方式,均可以保证User的roletype字段值只能是Role集合中已存在的内容:
1. 先定义Role Schema并导出模型
const mongoose = require('mongoose'); const { Schema } = mongoose; const roleSchema = new Schema({ userType: { type: String, required: true, unique: true // 避免重复的角色类型 } // 可扩展其他角色属性,比如权限列表、角色描述等 }); module.exports = mongoose.model('Role', roleSchema);
2. 定义User Schema并添加关联校验
方案1:通过ObjectId外键关联(推荐使用)
符合Mongoose标准关联规范,后续扩展角色属性更灵活:
const Role = require('./role'); // 导入已定义的Role模型 const userSchema = new Schema({ username: { type: String, required: true }, password: { type: String, required: true }, roletype: { type: Schema.Types.ObjectId, ref: 'Role', // 声明关联的模型是Role required: true, // 自定义异步校验,保证关联的角色真实存在 validate: { validator: async function(roleId) { const existRole = await Role.findById(roleId); return !!existRole; }, message: props => `传入的角色ID ${props.value} 不存在于Role集合中` } } }); module.exports = mongoose.model('User', userSchema);
后续查询用户数据时,调用.populate('roletype')即可自动关联查出对应的Role完整数据。
方案2:直接存储userType文本值
适合不需要额外角色属性、希望User里直接存可读角色名的场景:
const Role = require('./role'); const userSchema = new Schema({ username: { type: String, required: true }, password: { type: String, required: true }, roletype: { type: String, required: true, // 自定义异步校验,保证传入的角色名已经在Role中创建 validate: { validator: async function(typeVal) { const existRole = await Role.findOne({ userType: typeVal }); return !!existRole; }, message: props => `传入的角色类型 ${props.value} 不存在于Role集合中` } } }); module.exports = mongoose.model('User', userSchema);
注意事项
- 上述校验默认只在调用
save()、create()方法时触发,如果使用updateMany()、findOneAndUpdate()等更新方法,需要添加runValidators: true配置才会触发校验,示例:User.findOneAndUpdate({_id: xxx}, {roletype: newRole}, {runValidators: true}) - 如果Role集合数据量较大,可将所有角色值缓存到内存中,校验时直接查缓存减少数据库查询开销。
内容的提问来源于stack exchange,提问作者Hesham Eldawy
相关产品推荐
相关产品推荐

