Tìm kiếm trang web

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);
 }
}