NestJS中实现独立Mongo集合的Mongoose Schema继承失败如何解决
现有方案问题说明
- 第一种方案问题:子类
PersonSchemaDefinition未添加@Schema()装饰器,SchemaFactory.createForClass无法正确读取子类的@Prop元数据,且没有手动合并基类的schema配置,导致只有基类字段生效。 - 第二种方案问题:使用
Object.assign直接合并类和schema.obj,类的装饰器元数据不会被浅拷贝,合并后的对象不是合法的Mongoose Schema实例,因此子类字段无法识别。
正确实现方案
1. 修正基础Schema(base.schema.ts)
import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose'; import { Document, Types } from 'mongoose'; import { TimeStamps } from './timestamps.schema'; export type BaseDocument = BaseSchemaDefinition & Document; @Schema({ toJSON: { virtuals: true, transform: function (doc: any, ret: any) { delete ret._id; delete ret.__v; return ret; }, }, }) export class BaseSchemaDefinition { @Prop({ type: Types.ObjectId, required: true, default: Types.ObjectId, }) nonce: Types.ObjectId; @Prop() timestamps: TimeStamps; } export const BaseSchema = SchemaFactory.createForClass(BaseSchemaDefinition); // 公共虚拟字段统一放在基类,所有子类自动继承 BaseSchema.virtual('id').get(function (this: BaseDocument) { return this._id.toHexString(); });
2. 修正业务Schema(person.schema.ts)
import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose'; import * as mongoose from 'mongoose'; import { Document } from 'mongoose'; import { Address } from './address.schema'; import { BaseSchema, BaseSchemaDefinition } from './base.schema'; export type PersonDocument = PersonSchemaDefinition & Document; // 子类必须添加@Schema装饰器 @Schema() export class PersonSchemaDefinition extends BaseSchemaDefinition { @Prop({ required: true }) first_name: string; @Prop({ required: true }) last_name: string; @Prop() middle_name: string; // 注意原代码拼写错误:data_of_birth修正为date_of_birth,避免字段不匹配 @Prop() date_of_birth: Date; @Prop({ type: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Address' }] }) addresses: Address[]; } // 先创建子类原生Schema export const PersonSchema = SchemaFactory.createForClass(PersonSchemaDefinition); // 合并基类字段配置 PersonSchema.add(BaseSchema.obj); // 继承基类全局配置(toJSON等) PersonSchema.set('toJSON', BaseSchema.get('toJSON')); // 继承基类所有虚拟字段 Object.keys(BaseSchema.virtuals).forEach(virtualName => { PersonSchema.virtual(virtualName).get(BaseSchema.virtuals[virtualName].getters[0]); });
3. 验证模块注册配置
确保对应业务模块中Mongoose模型注册使用修正后的Schema:
import { Module } from '@nestjs/common'; import { MongooseModule } from '@nestjs/mongoose'; import { PersonSchemaDefinition, PersonSchema } from './person.schema'; import { PersonService } from './person.service'; @Module({ imports: [ MongooseModule.forFeature([{ name: PersonSchemaDefinition.name, schema: PersonSchema }]) ], providers: [PersonService] }) export class PersonModule {}
内容的提问来源于stack exchange,提问作者thxmike
相关产品推荐
相关产品推荐

