Rails渴望加载和where子句 [英] Rails Eager Loading and where clause
问题描述
我渴望加载带有关联的模型对象:
I'm eager loading a model object with its associations:
user= User.includes(:posts).find(1)
但是在代码的某些时候,我想做这样的事情:
But then at certain points in the code I would like to do something like this:
user.posts.where(:topic => "x")
但这只是再次重新运行查询。因此,我想我应该这样做:
But that just re-runs the query again. So instead I thought I'd do this:
user.posts.select{|post| post.topic == "x" }
不会重新运行查询。但是我有几个问题。
That doesn't re-run the query. But I have a couple of questions.
首先,这是正确的做法吗?
First, Is this the right way to do it?
第二个,我对select在这种情况下的操作感到有些困惑。因为即使在我没有使用include函数的情况下运行最后一行时,它还是第一次运行查询,然后在再次运行查询时却没有运行..那么是否涉及某种缓存?
因为当我使用where子句时,它每次都会运行查询。
Second, I'm a bit confused about what select does in this case. Because when I run the last line even when I haven't used the includes function, the first time it runs the query and then after that if I run it again, it doesn't .. so is there some sort of caching involved? Because when i use the where clause it runs the query every single time.
谢谢。
推荐答案
select
是Enumerable上的Ruby方法。第一次运行
select
is a Ruby method on Enumerable. The first time you run
user.posts.select{|post| post.topic == "x" }
所有 Post $ c
用户
的:posts
关联的$ c>实例将从数据库加载到内存中;专门放入ActiveRecord集合对象中。然后在此集合上调用 select
,用过滤出集合中的所有
属性,除了 Post
实例:topic x
以外。
all Post
instances for user
's :posts
association will be loaded from the database into memory; specifically into an ActiveRecord collection object. select
is then called on this collection, filtering out all Post
instances in the collection with a :topic
attribute that is anything other than "x"
.
运行上面的第二行不会再次查询数据库,因为您已经将帖子
加载到内存中。
Running the above line a second time won't query the database again, because you've already loaded the posts
into memory.
当您执行如下所示的包含
user= User.includes(:posts).find(1)
it将渴望为返回的每个 User
实例加载:posts
关系(在这种情况下,单个 User
,其中:id
是 1
)。现在,您已按照上一节中的说明将所有 Post
个实例加载到内存中。
it is going to eager load the :posts
relation for each User
instance returned (in this case, a single User
where :id
is 1
). You now have all Post
instances loaded into memory as described in the previous section above.
如果您这样做了像
user.posts.where(:topic => "x")
您现在要告诉Rails对 Post
new 查询>,这一次找到了所有 Post
实例,其中:topic
是 x
,其中:user_id
是用户$的
:id
c $ c>。 其中
在内存中的Arel集合上不能像过滤器一样工作。
you are now telling rails to run a new query against Post
, this time finding all Post
instances where :topic
is "x"
and where :user_id
is the :id
of the user
. where
doesn't work like a "filter" on an in-memory ARel collection.
- 如果要避免出现另一个不好的查询,
select
是过滤内存结果集的一种好方法 - 您可以运行基准测试以找出更快的速度:
- If you want to avoid another query that bad,
select
is a fine way to filter the in-memory result set. - You could run benchmarks to find which is faster:
- 查询数据库并将另一个ARel集合重新填充到内存中
- 迭代内存中的可编号对象,并使用Ruby运行过滤器
如果不需要所有与用户
相关的:帖子
,您可以轻松地将其包含在原始查询中
If you never need all related :posts
for user
, you can easily include this in the original query
user.includes(:posts).where("posts.topic = ?", 'x')
这篇关于Rails渴望加载和where子句的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!