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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 16:57:32