字符串_id转换为mongoose ObjectId未得到预期结果
问题原因
从API拿到的JSON格式MongoDB文档,_id字段大概率是MongoDB Extended JSON格式的嵌套对象,结构为{ $oid: "24位十六进制ID字符串" },而非直接的ID字符串。
当把这类嵌套对象传入mongoose.Types.ObjectId()构造函数时,函数无法识别合法输入参数,会直接生成一个全新的随机ObjectId实例,不会保留传入的原始ID值。
可以先加一行日志确认该情况:
console.log('收到的_id类型与值:', typeof doc.data._id, doc.data._id) // 预期输出: object { '$oid': 'xxxxxxxxxxxxxxxxxxxxxxxx' }
修复方法
先从返回结构里提取出纯24位十六进制ID字符串,再做类型转换即可:
- 修改创建文档实例时的
uuid字段赋值逻辑
.then((doc) => { console.log(doc.data); // 提取原始ID字符串,兼容直接返回字符串和返回$oid嵌套对象两种场景 const rawObjectId = typeof doc.data._id === 'object' ? doc.data._id.$oid : doc.data._id; // 可选:加一层合法性校验,避免非法值存入 if (!mongoose.Types.ObjectId.isValid(rawObjectId)) { throw new Error(`收到的_id格式非法,值为:${rawObjectId}`); } let newRecord = new postsModel({ caption: req.body.caption, post_type: req.body.post_type, content: req.body.content, uuid: rawObjectId, // Mongoose会根据Schema定义自动转成ObjectId类型,无需手动调用构造函数 posted_datetime: new Date(), last_updated_datetime: new Date(), }); newRecord .save() .then((d) => { res.json(d); console.log('New post added!'); }) .catch((err) => { console.log(err); }); })
- 校验转换结果:转换完成后可以对比ID值确认一致性
// 保存前可加日志验证 console.log('原始ID值:', rawObjectId); console.log('转换后存入的ID值:', newRecord.uuid.toHexString()); // 两个值完全相等即表示转换正确
补充说明
Mongoose v6+版本中,mongoose.Types.ObjectId与mongoose.Schema.Types.ObjectId完全等价,只要传入的原始ID字符串合法,存入uuid字段的值就会和外部API返回的_id完全一致,可正常作为跨集合关联的外键使用。
内容的提问来源于stack exchange,提问作者mukund deepak
相关产品推荐
相关产品推荐

