Mongoose使用Object.values提取文档字段值失效如何解决
问题产生原因
- Mongoose的
find()方法默认返回的是Mongoose Document实例数组,不是原生JavaScript纯对象:这类实例上挂载了大量Mongoose内置的内部属性、原型方法,直接对实例调用Object.values()会拿到这些内置属性/方法,而非你在Schema中定义的业务字段值。 - 代码逻辑存在疏漏:
find()返回的结果s永远是数组(哪怕匹配到的结果只有1条,也是长度为1的数组),你直接对s调用Object.values()遍历,拿到的第一个元素就是完整的单条文档实例,自然会输出整个原文档对象。 - 原代码存在语法错误:
console.log(val));多写了一个右括号,运行时会直接抛出语法异常。
可行解决方案
- 方案1:将Mongoose文档转为普通对象后再提取字段值
用Mongoose文档自带的toObject()方法把Document实例转为原生JS对象,过滤掉内置的id等非业务字段后再取值:Name.find(function(err, s){ if (err){ console.log(err); return; } mongoose.connection.close(); // 单条结果取数组第一项,多条结果可循环遍历s数组 const plainDoc = s[0].toObject(); // 过滤_id、__v等Mongoose内置字段 const res = Object.entries(plainDoc) .filter(([key]) => !['_id', '__v', 'id'].includes(key)) .map(([,val]) => val) .join(' '); console.log(res); // 输出 Jeff Ricky Lexi Eric }); - 方案2:查询时调用
lean()直接返回纯JS对象
链式调用.lean()后,Mongoose不会再将返回结果包装为Document实例,直接返回原生JS对象,性能更好也更方便后续处理:Name.find().lean(function(err, s){ if (err){ console.log(err); return; } mongoose.connection.close(); const plainDoc = s[0]; const res = Object.entries(plainDoc) .filter(([key]) => !['_id', '__v'].includes(key)) .map(([,val]) => val) .join(' '); console.log(res); }); - 方案3:查询时通过投影指定返回字段,从根源避免多余字段干扰
如果你明确只需要目标name相关字段,可以在查询时通过投影参数指定只返回需要的字段,直接排除_id等不需要的字段,后续可以直接提取值:// 第二个参数为投影配置:_id:0表示不返回id字段,其余几个字段设为1表示需要返回 Name.find({}, {_id:0, name:1, name1:1, name2:1, name3:1}).lean(function(err, s){ if (err){ console.log(err); return; } mongoose.connection.close(); console.log(Object.values(s[0]).join(' ')); });
补充说明:如果你的业务场景是只查询单条数据,建议直接用
findOne()替代find(),返回的结果直接是单条文档/对象,不需要额外取数组第一项,逻辑更简洁。
内容的提问来源于stack exchange,提问作者Vicky
相关产品推荐
相关产品推荐

