NodeJS+Mongoose环境下console.log为何遗漏对象键对?
问题分析与解决方案
这事儿我之前调试Mongoose项目时也碰到过,其实核心原因是:你通过Booking.findById拿到的booking并不是普通的JavaScript对象,而是Mongoose Document实例——这是Mongoose封装的ORM对象,自带了一堆内部属性(就是你看到的$__、isNew这些),而实际的业务数据都存在它的_doc属性里。
为什么两种打印结果不一样?
- 直接
console.log(booking)时,Mongoose的Document对象重写了控制台的inspect方法,会自动展示_doc里的业务数据,所以你能看到_id、user这些实际字段; - 但
Object.keys()只会遍历对象自身的可枚举属性,而Mongoose把业务数据存在_doc里,没有直接挂载到Document实例上,所以你只能拿到那些内部属性的键。
解决方法
有两种常用方式可以拿到业务数据的所有键:
1. 把Document转换成普通JS对象
用Mongoose提供的toObject()方法,将Document实例转为纯JS对象,之后就能正常用Object.keys()了:
Booking.findById({_id: args.bookingID}) .populate('event') .then(booking => { const plainBooking = booking.toObject(); console.log(plainBooking); // 和之前打印的内容一致,但现在是普通对象 console.log(Object.keys(plainBooking)); // 会输出['_id', 'user', 'event', 'createdAt', ...] });
2. 查询时直接返回普通对象
如果你的场景只需要读取数据,不需要后续调用Mongoose的Document方法(比如save()、update()),可以在查询时添加lean: true选项,让Mongoose直接返回原生JS对象:
Booking.findById({_id: args.bookingID}) .populate('event') .lean() // 开启lean模式 .then(booking => { console.log(booking); // 直接是普通JS对象 console.log(Object.keys(booking)); // 正常输出所有业务键 });
这种方式还能提升查询性能,因为Mongoose不需要创建复杂的Document实例。
内容的提问来源于stack exchange,提问作者user12544591
相关产品推荐
相关产品推荐

