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

Mongoose v6/v7中自定义'id'虚拟属性为何返回String而非ObjectId?

Mongoose v6/v7中自定义'id'虚拟属性返回String而非ObjectId的解决方法

问题描述

我有一个使用Mongoose v5的Node.js项目,升级到Mongoose v6后发现自定义的id虚拟属性不再返回ObjectId,而是变成了String。进一步排查后确认,这个问题只出现在名为id的虚拟属性上。

最小复现代码

user.js

const mongoose = require('mongoose');

const userSchema = new mongoose.Schema({
  name: String,
});

userSchema.virtual('id').get(function() {
  return this._id;
});

module.exports = mongoose.model('User', userSchema);

index.js

const mongoose = require('mongoose');
const UserModel = require('./user');

async function main() {
  let dbUrl = 'mongodb://username:password@localhost/assess?authSource=admin&directConnection=true';
  await mongoose.connect(dbUrl);
  let user = await new UserModel({ name: 'Jim' });
  console.log(`in Mongoose v${mongoose.version}, user.id has type ${user.id.constructor.name}`);
  await mongoose.disconnect();
}

main();

版本输出差异

$ npm i mongoose@5
$ node index.js
in Mongoose v5.13.17, user.id has type ObjectID

$ npm i mongoose@6
$ node index.js
in Mongoose v6.11.2, user.id has type String

$ npm i mongoose@7
$ node index.js
in Mongoose v7.2.4, user.id has type String

尽管虚拟属性的get函数明确返回this._id(ObjectId类型),但在v6和v7中返回值被自动转为String,需要阻止这种转换。

原因分析

Mongoose从v6开始,默认给所有文档添加了内置的id虚拟属性,该属性会自动将_id转换为String类型。自定义的id虚拟属性会被Mongoose的内置实现覆盖,导致最终返回String而非预期的ObjectId。

解决方法

方法1:禁用内置的id虚拟属性

在定义Schema时,通过id: false配置项关闭Mongoose内置的id虚拟属性,这样自定义的id虚拟属性就能正常返回ObjectId:

const userSchema = new mongoose.Schema({
  name: String,
}, { id: false }); // 添加该选项关闭内置id虚拟属性

userSchema.virtual('id').get(function() {
  return this._id;
});

方法2:重命名自定义虚拟属性

如果需要保留内置的id属性(用于获取String类型的ID),可以将自定义的虚拟属性重命名,比如objectId:

userSchema.virtual('objectId').get(function() {
  return this._id;
});

之后通过user.objectId即可获取到ObjectId类型的ID值。

内容的提问来源于stack exchange,提问作者Joel Harris

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 00:05:16