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']
), то будет запущен только первый запрос, и в итоге вы получите незаполненные книги (но Автору будет запрошено объединенное условие).