sql - Rails:如何在自定义关联列时在单个查询中加载关联
问题描述
如果我使用eager_load
在单个查询中获取我想要的关联,我会得到太多列:
scope = Product.eager_load(:account).to_a
scope.last.account.name
然后我得到一个查询,如下所示:
SQL (3.3ms) SELECT "products"."id" AS t0_r0, "products"."account_id" AS t0_r1, "products"."notes" AS t0_r2, "products"."created_at" AS t0_r3, "products"."updated_at" AS t0_r4, "products"."rep_id" AS t0_r5, "products"."senior_rep_id" AS t0_r6, "products"."name_id" AS t0_r7...
我的目标是获得我想要的列,例如我可能期望通过调用.select("intakes.id, intakes.account_id, accounts.id, accounts.name")
. 但是,如果我将其添加到我的查询中,它只是将该行添加到前面并基本上忽略它:
SQL (3.3ms) SELECT products.id, products.account_id, accounts.id, accounts.name, "products"."id" AS t0_r0, "products"."account_id" AS t0_r1, "products"."notes" AS t0_r2, "products"."created_at" AS t0_r3, "products"."updated_at" AS t0_r4, "products"."rep_id" AS t0_r5, "products"."senior_rep_id" AS t0_r6, "products"."name_id" AS t0_r7...
所以现在我的查询更长了,但我没有得到任何好处。我也可以尝试left_joins
:
scope = Product.left_joins(:account).select("products.id, products.account_id, accounts.id, accounts.name").to_a
这将产生 N+1 个查询,其中忽略关联的选择:
Products Load (0.9ms) SELECT products.id, products.account_id, accounts.id, accounts.name FROM "products" LEFT OUTER JOIN "accounts" ON "accounts"."id" = "products"."account_id"
Account Load (0.2ms) SELECT "accounts".* FROM "accounts" WHERE "accounts"."id" = $1 LIMIT $2 [["id", 16], ["LIMIT", 1]]
但是,如果我识别出选定的列 DID 去某个地方,我可以避免 N+1,在那个accounts.name
映射到name
产品上:
scope.last.attributes["name"]
从技术上讲,这在单个查询中获得了我想要的信息,但是当构建具有许多关联的真实查询时,尝试重命名并将此数据重新映射为许多自定义名称突然让我想知道为什么我首先使用 ActiveModel。是否有更多的“Rails Way”来做到这一点,scope.last.account.name
它的价值仍然会以我使用的方式设置eager_load
?
解决方案
您可以留下查询scope = Product.left_joins(:account).select("products.id, products.account_id, accounts.id, accounts.name").to_a
,而不是您的第二行应该scope.last.name
阻止第二个数据库请求。如果您在 account 和 product 表中有相同的列,则在 select 方法中为它们设置不同的名称(即scope = Product.left_joins(:account).select("products.id, products.account_id, accounts.id, accounts.name as account_name").to_a
,而不是像scope.last.account_name
.
推荐阅读
- c++ - 如何正确显示特殊的中文、韩文、日文字符
- java - 如何使用扫描仪在给定多个输入的情况下获得多个输出
- google-analytics - 页面跳出率与退出页面跳出率的差异
- excel - 从另一个用户窗体调用时显示加载光标
- python - 为我的网络爬虫(Python、Selenium)查找多个 x_path
- python - 如何在python上一次将if语句设置为小于和大于?
- java - 为什么使用 for 循环会更改此字典类的输出?
- xamarin.forms - 页面出现时调用 Xamarin 窗体弹出页面按钮命令
- asp.net - 想要从模拟器连接到托管在 IIS 中的本地站点,而不是 localhost
- java - 是否可以将图像传输到 3 个不同的活动?