Mongoose Schema中roles字段Object.values返回undefined如何解决?
在MongoDB/Mongoose的用户Schema模型中,我定义了用户的roles字段如下:
const mongoose = require('mongoose') const {Schema} = mongoose const userSchema = new Schema({ username: {type: String, required: true}, password: {type: String, required: true}, roles: { User: {type: Number, default: 1234}, Editor: Number, Admin: Number, }, refreshToken: [String], }) module.exports = mongoose.model('User', userSchema)
所有角色均非必填,新注册用户默认拥有User角色(编码1234)。当通过Mongoose查询用户时:
const handleLogin = async (req, res) => { // ... const foundUser = await User.findOne({username: user}).exec() console.log(foundUser.roles) console.log(Object.values(foundUser.roles)) // ... }
控制台输出如下:
{ User: 2023 } [ 2023, undefined, undefined ]
数据库中仅存储了User字段,但Object.values()返回的结果里出现了两个undefined,希望理解原因并消除这些值。
Mongoose的文档对象(比如foundUser)不是普通的JavaScript对象,它会严格遵循你定义的Schema结构。即使数据库里没有存储Editor和Admin字段,当你访问foundUser.roles.Editor或foundUser.roles.Admin时,Mongoose会返回undefined来维持Schema定义的结构。因此Object.values()会遍历Schema中定义的三个子字段,自然就包含了这两个undefined值。
方法1:转换为普通JS对象后处理
Mongoose文档对象提供了toObject()或toJSON()方法,能把文档转换为只包含数据库实际存储字段的普通对象,这样遍历的时候就不会出现多余的undefined:
const plainUser = foundUser.toObject(); console.log(Object.values(plainUser.roles)); // 输出:[2023]
方法2:直接过滤undefined值
如果不想转换对象,可以直接对Object.values()的结果进行过滤,剔除undefined:
console.log(Object.values(foundUser.roles).filter(val => val !== undefined)); // 输出:[2023]
方法3:修改Schema为动态Object类型(可选)
如果你的角色不需要固定的字段结构,希望动态存储角色键值对,可以把roles定义为普通Object类型,而不是嵌套的固定字段:
const userSchema = new Schema({ // ...其他字段 roles: { type: Object, default: { User: 1234 } }, // ... })
这样Mongoose不会强制保留Editor和Admin的字段定义,查询返回的roles只会包含数据库中实际存在的角色键。
内容的提问来源于stack exchange,提问作者Keitaro

