You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 13:32:43