Петля 4: Отношение "многие ко многим"

Я пытаюсь реализовать способ фильтрации данных в таблицах, которые имеют отношение ManytoMany.

У меня есть следующие таблицы job, job_category и category.

Пока я подумываю сделать запрос к job_category с помощью job_id, а затем использовать этот результат для добавления условия с помощью IN (), но я также не нахожу способа повлиять на эту опцию.

Вопросов:

  1. Как реализовать отношение ManytoMany в Loopback 4?

  2. Как отфильтровать запрос с помощью IN?

PD Я могу использовать $ inq для вопроса № 2.

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

person Eduardo    schedule 12.03.2019    source источник


Ответы (2)


Принимая во внимание контекст вашего вопроса, отношение «многие ко многим» может быть реализовано в 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);
      }
    }

В модели отношений категорий должностей мы собираемся реализовать отношение принадлежит как к моделям должностей, так и к моделям категорий. Это обеспечит соотношение 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 для модели категорий заданий и использовать там методы поиска для извлечения данных. К сожалению, параметр includes в классе Filter для методов поиска еще не реализован в lb4. Это все еще WIP. Обратитесь к этой ветке из репозитория loopback-next для получения обновлений. А пока вам, возможно, придется добавить пользовательский логический t контроллер или классы репозитория для достижения этой цели. Ниже приведены два предложенных мной подхода.

  1. Настроить принадлежит отношению в репозитории (см. Документацию здесь) и использовать его внутри контроллера для получения ответа соответствующими данными (см. реализацию здесь). Для этого вам может потребоваться создать свою собственную модель ответа. Для этого мы создали собственный DTO. Вы также можете вернуть любой тип в качестве ответа для этого, но это не рекомендуется.
  2. При необходимости вы можете выполнить свой собственный запрос на соединение. Это собственный подход к запросам. Но, к сожалению, функция execute в классе репозитория еще не реализована. См. здесь. / а>. Однако он доступен в dts. Итак, мы реализовали обходной путь, пока не реализовали его. Мы создали базовый класс репозитория, который будет унаследован всеми классами репозитория в нашем приложении (заменив все extends 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 вы уже упомянули подход. Это работает.

person Samarpan    schedule 01.04.2019

Вы можете реализовать отношение «многие ко многим» в Loopback 4, используя отношение hasManyThrough. Отношение hasManyThrough является расширением отношения hasMany.

В настоящее время эта функция представляет собой пул-реквест, ожидающий принятия.

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

Однако код для этого запроса на вытягивание был упакован и может быть установлен и использован следующим образом.

npm install --save @loopback/repository@git+https://[email protected]/codejamninja/loopback-next.git#npm/codejamninja/[email protected]

модели / Patient.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[];
}

репозитории / 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

person Clay Risser    schedule 04.09.2019