извлекать все вложенные ресурсы по идентификатору ресурса по отношению ко многим - PullRequest
0 голосов
/ 11 октября 2019

Я хочу создать API NestJs с TypeORM и иметь две сущности: пользователи и группы . Пользователь может присоединиться к нескольким группам, а в группе может быть несколько пользователей.

Я создал эти модели ORM для пользователя

@Entity('User')
export class UserEntity {
  @PrimaryGeneratedColumn()
  id: number;

  // ...

  @ManyToMany((type: any) => GroupEntity, (group: GroupEntity) => group.users)
  @JoinTable()
  groups: GroupEntity[];
}

и для группы

@Entity('Group')
export class GroupEntity {
  @PrimaryGeneratedColumn()
  id: number;

  // ...

  @ManyToMany((type: any) => UserEntity, (user: UserEntity) => user.groups)
  @JoinTable()
  users: UserEntity[];
}

При вызове маршрута GET localhost:3000/users/1/groups я хочу вернуть массив групп, к которым принадлежит пользователь. UsersService выполняет это

const groups: GroupEntity[] = await this.groupsRepository.find({
  where: { userId: 1 },
  relations: ['users'],
});

При вызове маршрута GET localhost:3000/groups/1/users Я хочу вернуть массив пользователей, которых удерживает группа. GroupsService выполняет это

const users: UserEntity[] = await this.usersRepository.find({
  where: { groupId: 1 },
  relations: ['groups'],
});

К сожалению, обе конечные точки возвращают каждый вложенный подресурс. Кажется, предложение where игнорируется. База данных создает две кросс-таблицы

enter image description here

, но можно ожидать только одну кросс-таблицу, потому что одна из них избыточна, нет? Конечно, это может иметь технические причины. Как правильно выбрать субресурсы?

1 Ответ

1 голос
/ 11 октября 2019

Первая проблема

В TypeORM, когда вы определяете отношение @ManyToMany, вам нужно использовать @JoinTable на одной (собственной) стороне отношения.

Таким образом, это создасттолько одна кросс-таблица.

Пример

@Entity('User')
export class UserEntity {
  @PrimaryGeneratedColumn()
  id: number;

  // ...

  @ManyToMany((type: any) => GroupEntity, (group: GroupEntity) => group.users)
  @JoinTable()
  groups: GroupEntity[];
}

@Entity('Group')
export class GroupEntity {
  @PrimaryGeneratedColumn()
  id: number;

  // ...

  @ManyToMany((type: any) => UserEntity, (user: UserEntity) => user.groups)
  users: UserEntity[];
}

It will generate three tables users, groups, and user_groups_group

Вторая задача

Вы можете использовать этот запрос

user = await userRepo.find({
    relations: ['groups'],
    where: { id: user.id }
});
const groups = user.groups

И поскольку ваш код предполагает, что вы используете отложенную загрузку typeORM, вы можете сделать это

const user = await userRepo.find({
    where: { id: someId }
});
const groups = await note.groups
...