TypeORM:如何在不使用 JOIN 的情况下使用 CreateQueryBuilder 加载关系?

发布于 2025-01-16 18:40:46 字数 1277 浏览 3 评论 0原文

我正在使用 NestJS 开发 API输入 ORM 从 MySQL DB 获取数据。目前,我正在尝试获取实体(HearingTonalTestPage)的所有实例以及所有相关实体(例如Frequency)。我可以使用 createQueryBuilder 获取它:

const queryBuilder = await this.hearingTonalTestPageRepo
      .createQueryBuilder('hearing_tonal_test_page')
      .innerJoinAndSelect('hearing_tonal_test_page.hearingTest', 'hearingTest')
      .innerJoinAndSelect('hearingTest.page', 'page')
      .innerJoinAndSelect('hearing_tonal_test_page.frequencies', 'frequencies')
      .innerJoinAndSelect('frequencies.frequency', 'frequency')
      .where(whereConditions)
      .orderBy(`page.${orderBy}`, StringToSortType(pageFilterDto.ascending));

这里的问题是,这将生成一个 SQL 查询(下面的屏幕截图),该查询将为每个相关实体(Frequency)输出一行,当我想为每个 HearingTonalTestPage 输出一行(在屏幕截图示例中,是 3 行而不是 12 行),而不丢失其关系数据。阅读文档,显然这可以使用 .find() 的关系选项轻松实现。使用QueryBuilder,我看到了一些关系方法,但从我读到的来看,它在幕后会产生 JOIN,这当然是我想避免的。

SQL 结果query

因此,这里的 100 万美元问题是:是否可以使用 CreateQueryBuilder 在查询主要实体之后加载关系(类似于 >.查找({关系:{ } }) )?如果是,我怎样才能实现它?

I'm developing an API using NestJS & TypeORM to fetch data from a MySQL DB. Currently I'm trying to get all the instances of an entity (HearingTonalTestPage) and all the related entities (e.g. Frequency). I can get it using createQueryBuilder:

const queryBuilder = await this.hearingTonalTestPageRepo
      .createQueryBuilder('hearing_tonal_test_page')
      .innerJoinAndSelect('hearing_tonal_test_page.hearingTest', 'hearingTest')
      .innerJoinAndSelect('hearingTest.page', 'page')
      .innerJoinAndSelect('hearing_tonal_test_page.frequencies', 'frequencies')
      .innerJoinAndSelect('frequencies.frequency', 'frequency')
      .where(whereConditions)
      .orderBy(`page.${orderBy}`, StringToSortType(pageFilterDto.ascending));

The problem here is that this will produce a SQL query (screenshot below) which will output a line per each related entity (Frequency), when I want to output a line per each HearingTonalTestPage (in the screenshot example, 3 rows instead of 12) without losing its relations data. Reading the docs, apparently this can be easily achieved using the relations option with .find(). With QueryBuilder I see some relation methods, but from I've read, under the hood it will produce JOINs, which of course I want to avoid.

SQL result query

So the 1 million $ question here is: is it possible with CreateQueryBuilder to load the relations after querying the main entities (something similar to .find({ relations: { } }) )? If yes, how can I achieve it?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

情仇皆在手 2025-01-23 18:40:46

我不是专家,但我有一个类似的案例并使用:

const qb = this.createQueryBuilder("product");
        
// apply relations
FindOptionsUtils.applyRelationsRecursively(qb, ["createdBy", "updatedBy"], qb.alias, this.metadata, "");

return qb
    .orderBy("product.id", "DESC")
    .limit(1)
    .getOne();

它对我有用,所有关系都已正确加载。

参考: https://github.com/typeorm/ typeorm/blob/master/src/find-options/FindOptionsUtils.ts

I am not an expert, but I had a similar case and using:

const qb = this.createQueryBuilder("product");
        
// apply relations
FindOptionsUtils.applyRelationsRecursively(qb, ["createdBy", "updatedBy"], qb.alias, this.metadata, "");

return qb
    .orderBy("product.id", "DESC")
    .limit(1)
    .getOne();

it worked for me, all relations are correctly loaded.

ref: https://github.com/typeorm/typeorm/blob/master/src/find-options/FindOptionsUtils.ts

童话 2025-01-23 18:40:46

您说您想避免 JOIN,并且正在寻找 find({relations: {}}) 的类似物,但是 正如文档所述find({relations: {}}) 在幕后使用,预计是 LEFT JOIN。所以当我们谈论关系查询时,就不能没有JOIN。

现在关于问题:

这里的问题是这会产生一个 SQL 查询(截图
下面)将为每个相关实体(频率)输出一行,
当我想为每个 HearingTonalTestPage 输出一行时

您的查询看起来不错。而且查询的结果也没有问题。我认为您期望查询的结果类似于 json 结构(当关系字段包含其内部的所有信息而不是创建新行并将其所有值分布在几行上时)。但这就是 SQL 的工作原理。顺便说一句,getMany() 方法应该返回 3 个 HearingTonalTestPage 对象,而不是 12 个,因此 SQL 查询返回的内容不必让您担心。

主要问题:

是否可以使用 CreateQueryBuilder 加载关系
查询主要实体

我不明白你所说的“查询主要实体后”是什么意思。您能提供更多背景信息吗?

You say that you want to avoid JOINs, and are seeking an analogue of find({relations: {}}), but, as the documentation says, find({relations: {}}) uses under the hood, expectedly, LEFT JOINs. So when we talk about query with relations, it can't be without JOIN's.

Now about the problem:

The problem here is that this will produce a SQL query (screenshot
below) which will output a line per each related entity (Frequency),
when I want to output a line per each HearingTonalTestPage

Your query looks fine. And the result of the query, also, is ok. I think that you expected to have as a result of the query something similar to json structure(when the relation field contains all the information inside itself instead of creating new rows and spread all its values on several rows). But that is how the SQL works. By the way, getMany() method should return 3 HearingTonalTestPage objects, not 12, so what the SQL query returns should not worry you.

The main question:

is it possible with CreateQueryBuilder to load the relations after
querying the main entities

I did't get what do you mean by saying "after querying the main entities". Can you provide more context?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文