Rails渴望加载和where子句 [英] Rails Eager Loading and where clause

查看:78
本文介绍了Rails渴望加载和where子句的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我渴望加载带有关联的模型对象:

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 用户: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:

  1. 查询数据库并将另一个ARel集合重新填充到内存中

  2. 迭代内存中的可编号对象,并使用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屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆