NestJS 猫鼬模式继承
NestJS Mongoose Schema Inheritence
我试图在 NestJS 中继承 Mongoose Schemas 或 SchemaDefitions,但我运气不佳。
我这样做是为了共享基本和通用模式定义详细信息,例如虚拟 ('id') 和随机数,我们已附加到每个实体。每个模式定义都应该在 Mongo 中有自己的集合,因此鉴别器将不起作用。
我尝试通过以下不同的方式实现这一点
首先,我定义了以下基本架构定义:
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;
}
然后我继承架构定义并创建架构,以便稍后在我的服务和控制器中通过以下方式使用它:
person.schema.ts
import { Prop, SchemaFactory } from '@nestjs/mongoose';
import * as mongoose from 'mongoose';
import { Document } from 'mongoose';
import { Address } from './address.schema';
import { BaseSchemaDefinition } from './base.schema';
export type PersonDocument = PersonSchemaDefintion & Document;
export class PersonSchemaDefintion extends BaseSchemaDefinition {
@Prop({ required: true })
first_name: string;
@Prop({ required: true })
last_name: string;
@Prop()
middle_name: string;
@Prop()
data_of_birth: Date;
@Prop({ type: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Address' }] })
addresses: [Address];
}
const PersonSchema = SchemaFactory.createForClass(PersonSchemaDefintion);
PersonSchema.virtual('id').get(function (this: PersonDocument) {
return this._id;
});
export { PersonSchema };
这导致我只能创建和获取 BaseSchemaDefinition 中定义的属性。
{
"timestamps": {
"deleted": null,
"updated": "2021-09-21T16:55:17.094Z",
"created": "2021-09-21T16:55:17.094Z"
},
"_id": "614a0e75eb6cb52aa0ccd026",
"nonce": "614a0e75eb6cb52aa0ccd028",
"__v": 0 }
其次,然后我尝试使用此处描述的方法实现继承
(不同 MongoDB 集合)
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;
}
const BaseSchema = SchemaFactory.createForClass(BaseSchemaDefinition);
BaseSchema.virtual('id').get(function (this: BaseDocument) {
return this._id;
});
export { BaseSchema };
person.schema.ts
import { Prop } 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 = PersonSchemaDefintion & Document;
export class PersonSchemaDefintion extends BaseSchemaDefinition {
@Prop({ required: true })
first_name: string;
@Prop({ required: true })
last_name: string;
@Prop()
middle_name: string;
@Prop()
data_of_birth: Date;
@Prop({ type: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Address' }] })
addresses: [Address];
}
export const PersonSchema = Object.assign(
{},
BaseSchema.obj,
PersonSchemaDefintion,
);
结果相同。不确定为什么没有继承
以下是使用模式构建模型的服务代码
person.service.ts
import { Model } from 'mongoose';
import { Injectable } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import {
PersonSchemaDefintion,
PersonDocument,
} from 'src/schemas/person.schema';
import { TimeStamps } from 'src/schemas/timestamps.schema';
@Injectable()
export class PersonService {
constructor(
@InjectModel(PersonSchemaDefintion.name)
private personModel: Model<PersonDocument>,
) {}
async create(
personModel: PersonSchemaDefintion,
): Promise<PersonSchemaDefintion> {
personModel.timestamps = new TimeStamps();
const createdPerson = new this.personModel(personModel);
return createdPerson.save();
}
async update(
id: string,
changes: Partial<PersonSchemaDefintion>,
): Promise<PersonSchemaDefintion> {
const existingPerson = this.personModel
.findByIdAndUpdate(id, changes)
.exec()
.then(() => {
return this.personModel.findById(id);
});
if (!existingPerson) {
throw Error('Id does not exist');
}
return existingPerson;
}
async findAll(): Promise<PersonSchemaDefintion[]> {
return this.personModel.find().exec();
}
async findOne(id: string): Promise<PersonSchemaDefintion> {
return this.personModel.findById(id).exec();
}
async delete(id: string): Promise<string> {
return this.personModel.deleteOne({ _id: id }).then(() => {
return Promise.resolve(`${id} has been deleted`);
});
}
}
如果需要,我可以提供更多详细信息
在摆弄了一段时间之后,我发现了在利用这些技术时似乎有效的正确组合
这里是基地class
base.schema.ts
import { Prop, Schema } from '@nestjs/mongoose';
import { Document, Types } from 'mongoose';
import { TimeStamps } from './timestamps.schema';
export type BaseDocument = Base & Document;
@Schema()
export class Base {
@Prop({
type: Types.ObjectId,
required: true,
default: Types.ObjectId,
})
nonce: Types.ObjectId;
@Prop()
timestamps: TimeStamps;
}
继承base.schema
的class
person.schema.ts
import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
import { Document, Types } from 'mongoose';
import { Address } from './address.schema';
import { Base } from './base.schema';
export type PersonDocument = Person & Document;
@Schema({
toJSON: {
virtuals: true,
transform: function (doc: any, ret: any) {
delete ret._id;
delete ret.__v;
return ret;
},
},
})
export class Person extends Base {
@Prop({ required: true })
first_name: string;
@Prop({ required: true })
last_name: string;
@Prop()
middle_name: string;
@Prop()
data_of_birth: Date;
@Prop({ type: [{ type: Types.ObjectId, ref: 'Address' }] })
addresses: [Address];
}
const PersonSchema = SchemaFactory.createForClass(Person);
PersonSchema.virtual('id').get(function (this: PersonDocument) {
return this._id;
});
export { PersonSchema };
我唯一想改进的是将虚拟 ('id') 移动到基础 class。但是模式继承不起作用。此时,它仅适用于模式定义。这至少让我朝着正确的方向前进。如果有人有办法对此进行改进,请贡献。
我试图在 NestJS 中继承 Mongoose Schemas 或 SchemaDefitions,但我运气不佳。 我这样做是为了共享基本和通用模式定义详细信息,例如虚拟 ('id') 和随机数,我们已附加到每个实体。每个模式定义都应该在 Mongo 中有自己的集合,因此鉴别器将不起作用。
我尝试通过以下不同的方式实现这一点
首先,我定义了以下基本架构定义:
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;
}
然后我继承架构定义并创建架构,以便稍后在我的服务和控制器中通过以下方式使用它:
person.schema.ts
import { Prop, SchemaFactory } from '@nestjs/mongoose';
import * as mongoose from 'mongoose';
import { Document } from 'mongoose';
import { Address } from './address.schema';
import { BaseSchemaDefinition } from './base.schema';
export type PersonDocument = PersonSchemaDefintion & Document;
export class PersonSchemaDefintion extends BaseSchemaDefinition {
@Prop({ required: true })
first_name: string;
@Prop({ required: true })
last_name: string;
@Prop()
middle_name: string;
@Prop()
data_of_birth: Date;
@Prop({ type: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Address' }] })
addresses: [Address];
}
const PersonSchema = SchemaFactory.createForClass(PersonSchemaDefintion);
PersonSchema.virtual('id').get(function (this: PersonDocument) {
return this._id;
});
export { PersonSchema };
这导致我只能创建和获取 BaseSchemaDefinition 中定义的属性。
{ "timestamps": { "deleted": null, "updated": "2021-09-21T16:55:17.094Z", "created": "2021-09-21T16:55:17.094Z" }, "_id": "614a0e75eb6cb52aa0ccd026", "nonce": "614a0e75eb6cb52aa0ccd028", "__v": 0 }
其次,然后我尝试使用此处描述的方法实现继承
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;
}
const BaseSchema = SchemaFactory.createForClass(BaseSchemaDefinition);
BaseSchema.virtual('id').get(function (this: BaseDocument) {
return this._id;
});
export { BaseSchema };
person.schema.ts
import { Prop } 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 = PersonSchemaDefintion & Document;
export class PersonSchemaDefintion extends BaseSchemaDefinition {
@Prop({ required: true })
first_name: string;
@Prop({ required: true })
last_name: string;
@Prop()
middle_name: string;
@Prop()
data_of_birth: Date;
@Prop({ type: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Address' }] })
addresses: [Address];
}
export const PersonSchema = Object.assign(
{},
BaseSchema.obj,
PersonSchemaDefintion,
);
结果相同。不确定为什么没有继承
以下是使用模式构建模型的服务代码
person.service.ts
import { Model } from 'mongoose';
import { Injectable } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import {
PersonSchemaDefintion,
PersonDocument,
} from 'src/schemas/person.schema';
import { TimeStamps } from 'src/schemas/timestamps.schema';
@Injectable()
export class PersonService {
constructor(
@InjectModel(PersonSchemaDefintion.name)
private personModel: Model<PersonDocument>,
) {}
async create(
personModel: PersonSchemaDefintion,
): Promise<PersonSchemaDefintion> {
personModel.timestamps = new TimeStamps();
const createdPerson = new this.personModel(personModel);
return createdPerson.save();
}
async update(
id: string,
changes: Partial<PersonSchemaDefintion>,
): Promise<PersonSchemaDefintion> {
const existingPerson = this.personModel
.findByIdAndUpdate(id, changes)
.exec()
.then(() => {
return this.personModel.findById(id);
});
if (!existingPerson) {
throw Error('Id does not exist');
}
return existingPerson;
}
async findAll(): Promise<PersonSchemaDefintion[]> {
return this.personModel.find().exec();
}
async findOne(id: string): Promise<PersonSchemaDefintion> {
return this.personModel.findById(id).exec();
}
async delete(id: string): Promise<string> {
return this.personModel.deleteOne({ _id: id }).then(() => {
return Promise.resolve(`${id} has been deleted`);
});
}
}
如果需要,我可以提供更多详细信息
在摆弄了一段时间之后,我发现了在利用这些技术时似乎有效的正确组合
这里是基地class
base.schema.ts
import { Prop, Schema } from '@nestjs/mongoose';
import { Document, Types } from 'mongoose';
import { TimeStamps } from './timestamps.schema';
export type BaseDocument = Base & Document;
@Schema()
export class Base {
@Prop({
type: Types.ObjectId,
required: true,
default: Types.ObjectId,
})
nonce: Types.ObjectId;
@Prop()
timestamps: TimeStamps;
}
继承base.schema
的classperson.schema.ts
import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
import { Document, Types } from 'mongoose';
import { Address } from './address.schema';
import { Base } from './base.schema';
export type PersonDocument = Person & Document;
@Schema({
toJSON: {
virtuals: true,
transform: function (doc: any, ret: any) {
delete ret._id;
delete ret.__v;
return ret;
},
},
})
export class Person extends Base {
@Prop({ required: true })
first_name: string;
@Prop({ required: true })
last_name: string;
@Prop()
middle_name: string;
@Prop()
data_of_birth: Date;
@Prop({ type: [{ type: Types.ObjectId, ref: 'Address' }] })
addresses: [Address];
}
const PersonSchema = SchemaFactory.createForClass(Person);
PersonSchema.virtual('id').get(function (this: PersonDocument) {
return this._id;
});
export { PersonSchema };
我唯一想改进的是将虚拟 ('id') 移动到基础 class。但是模式继承不起作用。此时,它仅适用于模式定义。这至少让我朝着正确的方向前进。如果有人有办法对此进行改进,请贡献。