Node.js中Mongoose查询返回对象属性存在但访问返回undefined
异常原因
这是Mongoose的固有特性导致的,和JS语言本身无关:
Model.find()返回的结果集是Mongoose Document实例数组,不是原生JS普通对象。Document实例的属性通过原型链上的getter/setter实现访问,不是挂载在实例自身的自有属性,所以调用hasOwnProperty()检测所有属性都会返回false。- 访问
mainCategories返回undefined的核心原因:你的Categories Schema中没有定义mainCategories字段。Mongoose默认会过滤掉所有未在Schema中声明的字段,哪怕数据库中该字段实际存在,也不会被挂载到Document实例的访问器上,直接访问就会得到undefined。 - 你看到
console.log(categories[0])能打印出mainCategories,是因为Mongoose Document重写了console.log触发的inspect方法,会输出数据库返回的原始完整数据,和属性是否能通过点运算符直接访问没有关系。 - 前两个属性可以正常访问的原因:
_id是Mongoose Schema默认内置的字段,category是你已经在Schema中声明过的字段,这两个字段的访问器已经正常注册,所以可以正常读取。
修复方案
根据实际场景选择任意一种即可:
- 规范修复:在Categories的Schema定义中补充
mainCategories字段的类型声明,和数据库实际存储结构对齐
const categorySchema = new mongoose.Schema({ category: Array, // 补充mainCategories定义,可根据实际嵌套结构做更严格的格式校验 mainCategories: [{ id: Number, name: String, subCategories: Array }] }) module.exports = mongoose.model('Categories', categorySchema);
- 轻量修复:查询时追加
.lean()方法,让Mongoose直接返回原生JS普通对象,跳过Document实例化流程。这种方式不仅能正常读取所有数据库返回的字段,查询性能也比默认返回Document实例更高
// 追加.lean()调用 const categories = await Categories.find({}).lean(); // 后续所有属性访问、hasOwnProperty检测都会和普通对象表现完全一致
- 临时转换:拿到Document实例后调用
.toObject()方法手动转为普通对象再访问
const categories = await Categories.find({}); const firstCategory = categories[0].toObject(); console.log(firstCategory.mainCategories); // 可正常读取值 console.log(firstCategory.hasOwnProperty('mainCategories')); // 返回true
内容的提问来源于stack exchange,提问作者firstlord
相关产品推荐
相关产品推荐

