如何将MongoDB的versionKey __v映射为自定义字段?
解决Mongoose __v字段映射为自定义version字段的问题
方案1:用虚拟属性映射已有__v字段
如果你的集合已经存在__v字段、不想修改数据库结构,可以用Mongoose的虚拟属性实现字段映射:
- 在Schema中定义虚拟属性
version,关联底层的__v字段 - 配置Schema的序列化选项,确保虚拟属性在返回数据时被包含
- 同步更新TypeScript接口
IArticle,添加version字段
代码示例:
// 定义TypeScript接口 interface IArticle { title: string; overview: string; version?: number; // 对应__v的虚拟字段 } const articleSchema = new Schema<IArticle>({ title: { type: String, required: true, }, overview: { type: String, required: true, }, }, { // 配置序列化时包含虚拟属性 toJSON: { virtuals: true }, toObject: { virtuals: true } }); // 定义虚拟属性,映射__v到version articleSchema.virtual('version').get(function(this: IArticle & { __v?: number }) { return this.__v; }).set(function(this: IArticle & { __v?: number }, value: number) { this.__v = value; });
这种方式无需修改现有数据库数据,查询返回的结果会自动带上version字段,完全兼容GraphQL的命名规则;更新时也可通过version字段操作底层的__v,比如做乐观锁校验时,用__v: req.body.version作为查询条件即可。
方案2:直接修改Mongoose默认versionKey为version
如果你的集合还没有大量数据,或者可以接受修改数据库字段,更直接的方式是替换Mongoose默认的版本字段名:
- 创建Schema时通过
versionKey选项指定自定义字段名version - 可选:在Schema中显式定义
version字段,让TypeScript类型更严谨 - 更新TypeScript接口
IArticle
代码示例:
interface IArticle { title: string; overview: string; version?: number; } const articleSchema = new Schema<IArticle>({ title: { type: String, required: true, }, overview: { type: String, required: true, }, // 可选:显式定义version字段,增强类型提示 version: { type: Number, default: 0 } }, { // 将默认版本字段从__v改为version versionKey: 'version' });
这种方式下,数据库中存储的版本字段直接是version,和Schema、GraphQL定义完全一致,无需额外映射逻辑,更新时直接用version字段做乐观锁校验即可。
注意事项
- 方案1中,若要通过
version字段做更新校验,需确保查询条件对应底层的__v字段 - 方案2若遇到已存在
__v的旧数据,需手动迁移数据到version字段,否则会出现版本校验异常
内容的提问来源于stack exchange,提问作者AlleXyS
相关产品推荐
相关产品推荐

