TypeORM — отношение «многие ко многим», с условиями в объединенной таблице

#mysql #typeorm

#mysql #typeorm

Вопрос:

У меня есть отношение «многие ко многим» между podcasts таблицей и episodes таблицей. Подкаст может содержать несколько эпизодов, и эпизод может быть частью нескольких подкастов.

 @Entity({ name: 'podcasts' })
export class Podcast extends BaseEntity {
  @PrimaryGeneratedColumn()
  id: number;

  @ManyToMany(() => Episode, (episode) => episode.podcasts, { nullable: true })
  @JoinTable({ name: 'podcast_episode_join' })
  episodes: Episode[];
}

@Entity({ name: 'podcast_episodes' })
export class Episode extends BaseEntity {
  @PrimaryGeneratedColumn()
  id: number;

  @Column('boolean', { default: false })
  is_published: boolean;

  @ManyToMany(() => Podcast, (podcast) => podcast.episodes, { nullable: true, lazy: true })
  podcasts: Podcast[];
}
 

Я пытаюсь получить один подкаст (по его указанному идентификатору) со всеми его эпизодами, которые опубликованы ( is_published = true ). Мой приведенный ниже код работает хорошо.

Но: в случае, когда в моем подкасте нет эпизода, он ничего не возвращает ( undefined ) , вместо того, чтобы, по крайней мере, возвращать podcast объект (с пустым episodes свойством). Что я делаю не так?

 const podcast = await this.podcastRepository
  .createQueryBuilder('podcast')
  .leftJoinAndSelect('podcast.episodes', 'episode')
  .where('podcast.id = :id', { id })
  .andWhere('episode.is_published = :isPub', { isPub: true })
  .getOne();
 

Ответ №1:

Я наконец нашел, как это получить. Результаты были отфильтрованы только тогда, когда условие истинно : is_published = true . Но когда в подкасте нет эпизода, is_published есть null . Поэтому нам нужно проверить, является ли это свойство либо true или NULL .

Также мы должны быть уверены, что is_published столбец в episode таблице никогда не может быть NULL при создании новой строки. Что оно всегда имеет значение по умолчанию (здесь, в данном случае: false ).

 const podcast = await this.podcastRepository
  .createQueryBuilder('podcast')
  .leftJoinAndSelect('podcast.episodes', 'episode')
  .where('podcast.id = :id', { id })

  .andWhere(
    new Brackets((qb) => {
      qb
        // if episode is published
        .where('episode.is_published = :isPub', { isPub: true })
        // if there is no episode
        .orWhere('episode.is_published IS NULL', { isPub: true });
    }),
  )

  .getOne();