Mongoose给文档数组赋值时仅存入_id而非完整对象如何解决?
问题原因
- Mongoose关联字段内置转换逻辑:你的League Schema中
ties字段被定义为ObjectId类型的关联数组(配置了ref指向关联文档),当你对Mongoose文档实例的关联字段赋值时,Mongoose会自动触发字段setter,将传入的完整文档实例转换为对应的_id值,以匹配数据库层该字段仅存储ObjectId的设计规则。 - 运行环境差异:客户端运行正常是因为客户端拿到的是序列化后的普通JS对象,不存在Mongoose的内置setter逻辑,赋值时不会触发自动转换。
解决方案
根据你的业务场景选择以下两种方案即可:
方案1:转为普通JS对象操作(适用于仅需返回数据给前端、无需后续操作Mongoose实例的场景)
查询时添加lean()方法,直接返回无Mongoose元逻辑的普通对象,或者查询后手动调用toObject()/toJSON()转换:
// 查询时直接用lean(),性能更高 const league = await League.findById(查询参数).populate('ties').lean(); // 后续排序逻辑直接操作即可 const completed = []; const upcoming = []; league.ties.forEach((tie) => { if (!tie) return; tie.matchStatus === "COMPLETED" ? completed.push(tie) : upcoming.push(tie); }); upcoming.sort((a, b) => a.startDate - b.startDate); completed.sort((a, b) => b.startDate - a.startDate); league.ties = [...upcoming, ...completed];
方案2:绕过Mongoose setter(适用于需要保留Mongoose文档实例、后续要调用save()等方法的场景)
可以通过两种方式绕过自动转换逻辑:
// 方式A:使用set方法传入raw参数 league.set('ties', ties, { raw: true }); // 方式B:直接修改Mongoose内部存储原始数据的_doc属性 league._doc.ties = ties;
内容的提问来源于stack exchange,提问作者ACES
相关产品推荐
相关产品推荐

