node.js - Nestjs: gọi các hàm dịch vụ từ Model/Entity với các hook của sequelize
Trong NestJS, tôi phải sử dụng một service của module trong entity/model để điền dữ liệu vào chỉ mục elastic-search. Logic điền dữ liệu vào chỉ mục elastic search được viết trong Job.service.ts.
Tôi muốn gọi phương thức onCreate đó từ Job.service.ts từ các hook của sequelize có trong các model.
Đây là mã cho mô hình/thực thể Job.ts -
import { Table, Model, Column, AutoIncrement, PrimaryKey } from "sequelize-typescript";
@Table({ schema: "job", tableName: "job" })
export class Job extends Model<Job> {
@AutoIncrement
@PrimaryKey
@Column
id: number;
@Column
title: string;
@AfterCreate
static async jobAfterCreate(instance, options) {
// <--- need to call job service onCreate method here
}
@AfterUpdate
static async jobAfterUpdate() {}
@AfterDestroy
static async jobAfterDestroy() {}
}
và đây là mã cho Job.service.ts -
//imports not added
@Injectable()
export class JobService {
constructor(
@Inject("SEQUELIZE")
private readonly sequelizeInstance: Sequelize,
@Inject(forwardRef(() => ElasticsearchService))
private readonly elasticsearchService: ElasticsearchService,
@InjectModel(Job)
private jobModel: typeof Job
) {}
// here will write logic for updating elastic search index
async onCreate(instance, options){
console.log("ON CREATE INSTANCE:", instance);
console.log("ON CREATE OPTIONS:", options);
}
async onDestroy(instance, options){
console.log("ON DESTROY INSTANCE:", instance);
console.log("ON DESTROY OPTIONS:", options);
}
}
Tôi đã cố gắng tiêm service vào mô hình Job nhưng nó không hoạt động. Và tôi không thể viết logic elastic search trực tiếp bên trong mô hình vì cho việc đó tôi cần ElasticsearchService.
Câu trả lời #1
Giải pháp là ghi đè nhà cung cấp
Cách chính để đưa thông tin vào các mô hình là bằng cách ghi đè hành vi tiêm nhiễm.
Đầu tiên, bạn sẽ cần thêm một thuộc tính tĩnh tham chiếu đến dịch vụ trong mô hình của bạn.
Tôi sẽ sử dụng bộ phát sự kiện làm ví dụ ở đây.
Lớp Mẫu Của Bạn
import {Model, Table, Column, AfterCreate} from "sequelize-typescript";
import { EventEmitter2 } from "@nestjs/event-emitter";
@Table()
export class SomeModel extends <SomeModel> {
// this would be your referencing
public static EventEmitter: EventEmitter2;
@Column
public someColumn: string;
@AfterCreate
public static triggerSomeEvent(instance: SomeModel) {
SomeModel.EventEmitter.emit('YourEvent', instance);
}
}
Mô-đun nơi bạn sẽ sử dụng mô hình
Bây giờ chúng ta đang ghi đè quá trình tiêm mặc định.
import { EntitiesMetadataStorage } from '@nestjs/sequelize/dist/entities-metadata.storage';
import {
getConnectionToken,
getModelToken,
SequelizeModule,
} from '@nestjs/sequelize';
import { EventEmitter2 } from '@nestjs/event-emitter';
// The provider override
const modelInjector: Provider = {
provide: getModelToken(AccountabilityPartnerModel, DEFAULT_CONNECTION_NAME),
useFactory: (connection: Sequelize, eventEmitter: EventEmitter2) => {
SomeModel.EventEmitter = eventEmitter;
if (!connection.repositoryMode) {
return SomeModel;
}
return connection.getRepository(SomeModelas any);
},
inject: [getConnectionToken(DEFAULT_CONNECTION_NAME), EventEmitter2],
};
// Updating the meta information of sequelize-typescript package to handle connection injection in to the model overridden.
EntitiesMetadataStorage.addEntitiesByConnection(DEFAULT_CONNECTION_NAME, [
SomeModel,
]);
// our custom module being used rather than the Sequelize.forFeature([SomeModel])
const someModelModule: DynamicModule = {
module: SequelizeModule,
providers: [modelInjector],
exports: [modelInjector],
};
@Module({
imports: [someModelModule],
providers: [SomeService],
})
export class SomeModule {
}
Tiêm mô hình của bạn vào dịch vụ của bạn như bạn sẽ làm khi sử dụng Sequelize.forFeature và InjectModel được chỉ định như dưới đây.
@Injectable()
export class SomeService {
constructor(@InjectModel(SomeModel) someModel: typeof SomeModel) {}
public someFunction(data: any) {
this.someModel.EventEmitter.emit('YourEvent', data);
}
}
