有人能解释一下吗?
Project.includes([:user, :company])
这将执行3个查询,一个用于获取项目,一个用于获取这些项目的用户,一个用于获取公司。
Project.select("name").includes([:user, :company])
这将执行3个查询,并完全忽略选择位。
Project.select("user.name").includes([:user, :company])
这将执行1个带有正确左连接的查询,并且仍然完全忽略select。
在我看来,Rails忽略了带有includes的select。好吧,但是为什么当我把一个相关的模型放在select中时,它会从发出3个查询切换到发出1个查询呢?
请注意,1查询是我想要的,我只是无法想象这是正确的方式来获得它,也不知道为什么它的工作,但我不知道如何在一个查询中获得结果(.joins似乎只使用内部连接,我实际上并不想要,当我手动指定连接条件给.joins时,我们正在使用的搜索gem吓坏了,因为它试图重新添加同名的连接)。
6条答案
按热度按时间fjnneemd1#
我在select和includes中也遇到了同样的问题。对于关联模型的急切加载,我使用了本机Rails作用域“preload”http://apidock.com/rails/ActiveRecord/QueryMethods/preload,它提供了急切加载,而不会在作用域链中跳过“select”。
我在这里找到的https://github.com/rails/rails/pull/2303#issuecomment-3889821
希望这条建议对别人有帮助,就像对我有帮助一样。
a64a0gku2#
好吧,这是我想到的......
很好用,但它只在一个查询中得到了我需要的数据。唯一糟糕的是我必须给予所有东西一个model2别名,因为我们使用 meta_search,当你指定自己的连接条件时,它似乎无法判断一个表是否已经连接。
iecba09b3#
Rails在使用
include
或includes
时总是忽略select
参数。如果要使用select参数,请使用joins
。您可能在使用所讨论的查询gem时遇到问题,但是您也可以使用joins方法包含sql片段。
我不知道你的模式,所以我不得不猜测确切的关系,但这应该让你开始。
jhkqcmku4#
这里我可能遗漏了一些东西,但是
select
和include
不是ActiveRecord的一部分。通常的方法是这样的:更多例子请看api documentation。有时我不得不手动使用
find_by_sql
:希望这能给你指明正确的方向。
9njqaruj5#
我自己也想要这个功能,所以请使用它。在您的类中包含这个方法
字符串格式的#ACCEPTS参数“关联名称:列名称-列名称”
你可以这样称呼:Contract.includes_with_select('user:id-name-status','confirmation:confirmed-id'),它将选择那些指定的列。
p5fdfcr16#
preload
解决方案似乎不像eager_load
和includes
那样执行JOIN操作,因此为了获得最佳效果,我也编写了自己的解决方案,并将其作为我维护的与数据相关的gem**The Brick**的一部分发布。通过像这样覆盖
ActiveRecord::Associations::JoinDependency.apply_column_aliases()
****,当您添加.select(...)
时,它可以充当筛选器,以选择构建哪些列别名。加载了
gem 'brick'
之后,为了启用这种选择性行为,添加特殊列名:_brick_eager_load
作为.select(...)
中的第一个条目,这将在构建别名时启用列过滤。由于外键对于正确关联所有内容是必不可少得,因此它们是自动添加得,因此您不需要将它们包括在选择列表中.
希望它可以保存您的查询时间和一些内存!