Nest.js + Mikro-ORM: Коллекция сущностей не инициализирована при использовании createQueryBuilder и leftJoin

Я использую Nest.js и рассматриваю возможность перехода с TypeORM на Mikro-ORM. Я использую nestjs-mikro-orm модуль. Но я застрял на чем-то, что кажется очень простым...

У меня 3 объекта, AuthorEntity, BookEntity а также BookMetadata. От моегоAuthor модуль, я пытаюсь покинуть присоединиться к Book а также BookMetadata столы с createQueryBuilderметод. Но при выполнении своего запроса я получаю сообщение об ошибке, гдеCollection<BookEntity> of entity AuthorEntity[3390] not initialized. Однако столбцы изAuthor таблица хорошо извлекаются.

Мои 3 объекта:

@Entity()
@Unique({ properties: ['key'] })
export class AuthorEntity {
  @PrimaryKey()
  id!: number;

  @Property({ length: 255 })
  key!: string;

  @OneToMany('BookEntity', 'author', { orphanRemoval: true })
  books? = new Collection<BookEntity>(this);
}

@Entity()
export class BookEntity {
  @PrimaryKey()
  id!: number;

  @ManyToOne(() => AuthorEntity)
  author!: AuthorEntity;

  @OneToMany('BookMetadataEntity', 'book', { orphanRemoval: true })
  bookMetadata? = new Collection<BookMetadataEntity>(this);
}

@Entity()
@Unique({ properties: ['book', 'localeKey'] })
export class BookMetadataEntity {
  @PrimaryKey()
  id!: number;

  @Property({ length: 5 })
  localeKey!: string;

  @ManyToOne(() => BookEntity)
  book!: BookEntity;
}

И служебный файл, в котором я запускаю свой запрос:

@Injectable()
export class AuthorService {
  constructor(
    @InjectRepository(AuthorEntity)
    private readonly authorRepository: EntityRepository<AuthorEntity>,
  ) {}

  async findOneByKey(props: { key: string; localeKey: string; }): Promise<AuthorEntity> {
    const { key, localeKey } = props;

    return this.authorRepository
      .createQueryBuilder('a')
      .select(['a.*', 'b.*', 'c.*'])
      .leftJoin('a.books', 'b')
      .leftJoin('b.bookMetadata', 'c')
      .where('a.key = ?', [key])
      .andWhere('c.localeKey = ?', [localeKey])
      .getSingleResult();
  }
}

Я что-то пропустил? Может быть не связано, но я также заметил, что есть специальныйautoLoadEntities: true для пользователей TypeORM, использующих Nest.js. Есть что-то подобное для Mikro-ORM? Спасибо;)

1 ответ

Отображение нескольких сущностей из одного запроса пока не поддерживается, оно планируется в версии 4. Вы можете подписаться здесь: https://github.com/mikro-orm/mikro-orm/issues/440

В v3 вам нужно использовать 2 запроса для загрузки 2 сущностей, что для вашего варианта использования намного проще без участия QB.

return this.authorRepository.findOne({ key }, ['books']);

Или вы могли бы использовать qb.execute() чтобы получить необработанные результаты и сопоставить их самостоятельно, но вам также придется вручную присвоить всем полям псевдонимы, чтобы обойти дублирование (Author.name против Book.name), как и qb.select(['a.*', 'b.*']) приведет к запросу select a.*, b.* ... и повторяющиеся столбцы не будут правильно сопоставлены.

https://mikro-orm.io/docs/query-builder/

О autoLoadEntities вещь, никогда не слышала об этом, посмотрим, как это работает, но в целом адаптер nestjs не разработан мной, поэтому, если это что-то связано только с гнездом, было бы лучше спросить об их репозитории GH.

Или вы можете использовать обнаружение на основе папок (entitiesDirs).

вот новый пример с 3 объектами:

return this.authorRepository.findOne({ 
  key,
  books: { bookMetadata: localeKey } },
}, ['books.bookMetadata']);

Это создаст 3 запроса, по одному для каждой таблицы db, но первый будет автоматически соединять книги и bookMetadata, чтобы иметь возможность фильтровать по ним. Условие будет распространено вниз во втором и третьем запросах.

Если вы опустите параметр заполнения (['books.bookMetadata']), то будет запущен только первый запрос, и в итоге вы получите незаполненные книги (но Автору будет запрошено объединенное условие).

Другие вопросы по тегам