3

我正在尝试实现一种方法来过滤具有多对多关系的表中的数据。

我有以下表格工作、工作类别和类别。

到目前为止,我正在考虑使用 job_id 对 job_category 进行查询,然后使用该结果使用 IN() 添加条件,但我也没有找到任何方法来实现此选项。

问题:

  1. 如何在 Loopback 4 中实现多对多关系?

  2. 如何使用 IN 过滤查询?

PD 我可以将 $inq 用于问题 2。

filter.where = {
   ...filter.where,
   id: {inq: [2, 7]},
};
4

2 回答 2

5

考虑到您问题的上下文,可以在 lb4 中实现多对多关系,如下所示。

工作模型(示例) -

    @model({
      name: 'jobs',
    })
    export class Job extends Entity {
      @property({
        type: 'number',
        id: true,
      })
      id: number;

      @property({
        type: 'string',
        required: true,
      })
      name: string;

      // Other columns of the table.....

      constructor(data?: Partial<Job>) {
        super(data);
      }
    }

类别模型(样本) -

    @model({
      name: 'categories',
    })
    export class Category extends Entity {
      @property({
        type: 'number',
        id: true,
      })
      id: number;

      @property({
        type: 'string',
        required: true,
      })
      name: string;

      // Other columns of the table.....

      constructor(data?: Partial<Category>) {
        super(data);
      }
    }

在 Job 类别关系模型中,我们将使用 Job 和 Category 模型来实现属于关系。这将确保 m:n 关系。

    @model({
      name: 'job_categories',
    })
    export class JobCategory extends Entity {
      @property({
        type: 'number',
        id: true,
      })
      id: number;

      @belongsTo(() => Job)
      job_id: number;

      @belongsTo(() => Category)
      category_id: number;

      constructor(data?: Partial<JobCategory>) {
        super(data);
      }
    }

现在,使用 lb4 CLI,您可以为作业类别模型创建存储库和 REST 控制器,并使用其中的 find 方法来获取数据。不幸的是,在过滤器类中包含用于查找方法的参数尚未在 lb4 中实现。它仍然在制品。请参阅loopback-next repo 中的线程以获取更新。在此之前,您可能必须添加自定义逻辑 t 控制器或存储库类来实现此目的。下面是我建议的两种方法。

  1. 配置属于存储库中的关系(请参阅此处的文档)并在控制器内部使用它来获取相关数据的响应(请参阅此处的实现)。您可能需要为此创建自己的响应模型。为此,我们创建了自己的 DTO。您也可以返回“任何”类型作为对此的响应,但不建议这样做。
  2. 如果需要,您可以执行自己的连接查询。这是本机查询方法。但是,不幸的是,存储库类中的再次执行功能尚未实现。见这里。它虽然在 dts 中可用。因此,我们实施了一项工作,直到其实施。我们创建了一个 Base 存储库类,它将被我们应用程序中的所有存储库类继承(将所有扩展 DefaultCrudRepository替换为extends AppDefaultCrudRepository)。这是基本存储库的实现。
    export abstract class AppDefaultCrudRepository<
      T extends Entity,
      ID
    > extends DefaultCrudRepository<T, ID> {
      constructor(
        entityClass: typeof Entity & {
          prototype: T;
        },
        dataSource: AppDataSource,
      ) {
        super(entityClass, dataSource);
      }

      execute(
        command: Command,
        parameters: NamedParameters | PositionalParameters,
        options?: Options,
      ): Promise<AnyObject> {
        // Commented below statement until it is implemented in lb4
        // return super.execute(command, parameters, options);
        return this.dataSource.execute(command, parameters, options);
      }
    }

希望这对您的问题 #1 有所帮助。对于问题 #2,您已经提到了这种方法。这样可行。

于 2019-04-01T10:43:49.300 回答
1

您可以使用 hasManyThrough 关系在 Loopback 4 中实现多对多关系。hasManyThrough 关系是 hasMany 关系的扩展。

目前,此功能是一个等待接受的拉取请求。

https://github.com/strongloop/loopback-next/pull/2359

但是,此拉取请求的代码已经打包,可以通过以下方式安装和使用。

npm install --save @loopback/repository@git+https://git@github.com/codejamninja/loopback-next.git#npm/codejamninja/has-many-through-using-has-many@1.11.0-rc.1

模型/患者.model.ts

import { Entity, model, property, hasMany } from '@loopback/repository';
import { Appointment, Patient } from '../models';

@model()
export class Physician extends Entity {
  @property({
    type: 'string',
    id: true
  })
  id?: string;

  @hasMany(() => Patient, { through: () => Appointment })
  patients: Patient[];
}

存储库/患者.repository.ts

import {
  DefaultCrudRepository,
  HasManyThroughRepositoryFactory,
  repository
} from '@loopback/repository';
import { inject, Getter } from '@loopback/core';
import { MemoryDataSource } from '../datasources';
import { Patient, Physician } from '../models';
import { AppointmentRepository, PhysicianRepository } from '../repositories';

export class PatientRepository extends DefaultCrudRepository<
  Patient,
  typeof Patient.prototype.id
> {
  public readonly physicians: HasManyThroughRepositoryFactory<
    Physician,
    typeof Patient.prototype.id
  >;

  constructor(
    @inject('datasources.memory')
    dataSource: MemoryDataSource,
    @repository.getter('AppointmentRepository')
    getAppointmentRepository: Getter<AppointmentRepository>,
    @repository.getter('PhysicianRepository')
    getPhysicianRepository: Getter<PhysicianRepository>
  ) {
    super(Patient, dataSource);
    this.physicians = this.createHasManyThroughRepositoryFactoryFor(
      'physicians',
      getPhysicianRepository,
      getAppointmentRepository // notice the through repository getter
    );
  }
}

以下链接中有一个基本示例。

https://github.com/codejamninja/medical-practice-api

请注意,在接受拉取请求之前,此 api 可能会更改。

您可以在以下链接中阅读有关这种关系如何运作的更多信息。

https://loopback.io/doc/en/lb3/HasManyThrough-relations.html https://guides.rubyonrails.org/association_basics.html#the-has-many-through-association

于 2019-09-04T06:13:51.177 回答