Rails-通过关联加入 VS 检索
Rails-Joins VS Retrieval via Association
我对 when/how 使用 rails' 加入方法与 rails' 关联感到困惑。
我有一组对象以类似火车的方式相互链接:Class A
has_many: bs
和 Class B
has_many: cs
。我想在链接到链接到 A
的所有 B
的所有 c
上调用一个方法。我尝试用 a.bs.cs.some_method
做到这一点并得到
undefined method 'some_method' for #<bs::ActiveRecord_Associations_CollectionProxy:…>
四处搜索后,我开始明白这意味着 a.bs
returns 一个 CollectionProxy 对象,并且您不能调用方法——即使是 class c
有--在 c
个对象的 CollectionProxy 对象上。
我试图找出它应该如何完成,并遇到了 Joins
。现在我想知道是否应该使用嵌套连接来做这种事情?我以为我看到了一长串关联被用来做这件事,但我可能错了。
那么,我的问题是:
1-正确的做法是什么?
2-如果可以用 joins
和 关联链来完成,什么时候应该使用其中一个?
首先,如果您想获取关联对象或方法输出以进行收集,请使用collect
或map
。
即
a.bs.collect{|b| b.cs.collect(&:method_name)}.flatten.compact
现在上面的行将以数组格式为您提供结果,但它非常昂贵。为什么因为它会 运行 这样的查询
1) 获取 a
的第一个查询(很好)
2) 使用 IN 查询获取 a
的所有 bs
的第二个查询(这也很好,因为 IN 查询只是 1 个查询,不会花费那么多时间)
3) 第三:现在对于每个 b
它将尝试获取 cs
并且要获取的查询数量 cs
将取决于 b
的计数.这非常昂贵。
我们如何优化它
我们将 eager load cs
bs
在获取 bs 之后。这种方式不是每次都明确 运行ning 查询 cs
,而是 运行 一个 IN
的查询,这很好
a.bs.includes(:cs).collect{|b| b.cs.collect(&:method_name)}.flatten.compact
详情:
这将 运行 1 个要获取的查询 a
,1 个要获取关联的 bs
的查询
a
,然后是一个查询以获取 bs
的关联 cs
。
您可以从此 link 了解预加载概念,它在获取大规模数据时非常有用。
http://guides.rubyonrails.org/active_record_querying.html#eager-loading-associations
要获取详细信息,请尝试此操作
#fetch some object for a like this a = A.first
1) a.bs (this will fetch the bs for a in one query
2) a.bs.includes(:cs) (this will fetch cs as well as bs in two queries .1 query for bs and 1 query for cs)
3) a.bs.includes(:cs).collect{|b|} (this will display the bs object)
4) a.bs.includes(:cs).collect{|b| b.cs } (this will display c objects in an array in each b object i.e 2D array something like this #[[c1,c2], [c3,c4], ...]. where [c1, c2] belongs to b1
5) a.bs.includes(:cs).collect{|b| b.cs.collect(&:method_name)} (this will put the method names in array. you will see arrays in array because of bs has many cs. each single array inside big array represent one b
6) a.bs.includes(:cs).collect{|b| b.cs.collect(&:method_name)}.flatten.compact (This will make all 2D arrays in single array. read flatten and compact concept.)
我对 when/how 使用 rails' 加入方法与 rails' 关联感到困惑。
我有一组对象以类似火车的方式相互链接:Class A
has_many: bs
和 Class B
has_many: cs
。我想在链接到链接到 A
的所有 B
的所有 c
上调用一个方法。我尝试用 a.bs.cs.some_method
做到这一点并得到
undefined method 'some_method' for #<bs::ActiveRecord_Associations_CollectionProxy:…>
四处搜索后,我开始明白这意味着 a.bs
returns 一个 CollectionProxy 对象,并且您不能调用方法——即使是 class c
有--在 c
个对象的 CollectionProxy 对象上。
我试图找出它应该如何完成,并遇到了 Joins
。现在我想知道是否应该使用嵌套连接来做这种事情?我以为我看到了一长串关联被用来做这件事,但我可能错了。
那么,我的问题是:
1-正确的做法是什么?
2-如果可以用 joins
和 关联链来完成,什么时候应该使用其中一个?
首先,如果您想获取关联对象或方法输出以进行收集,请使用collect
或map
。
即
a.bs.collect{|b| b.cs.collect(&:method_name)}.flatten.compact
现在上面的行将以数组格式为您提供结果,但它非常昂贵。为什么因为它会 运行 这样的查询
1) 获取 a
的第一个查询(很好)
2) 使用 IN 查询获取 a
的所有 bs
的第二个查询(这也很好,因为 IN 查询只是 1 个查询,不会花费那么多时间)
3) 第三:现在对于每个 b
它将尝试获取 cs
并且要获取的查询数量 cs
将取决于 b
的计数.这非常昂贵。
我们如何优化它
我们将 eager load cs
bs
在获取 bs 之后。这种方式不是每次都明确 运行ning 查询 cs
,而是 运行 一个 IN
的查询,这很好
a.bs.includes(:cs).collect{|b| b.cs.collect(&:method_name)}.flatten.compact
详情:
这将 运行 1 个要获取的查询 a
,1 个要获取关联的 bs
的查询
a
,然后是一个查询以获取 bs
的关联 cs
。
您可以从此 link 了解预加载概念,它在获取大规模数据时非常有用。 http://guides.rubyonrails.org/active_record_querying.html#eager-loading-associations
要获取详细信息,请尝试此操作
#fetch some object for a like this a = A.first
1) a.bs (this will fetch the bs for a in one query
2) a.bs.includes(:cs) (this will fetch cs as well as bs in two queries .1 query for bs and 1 query for cs)
3) a.bs.includes(:cs).collect{|b|} (this will display the bs object)
4) a.bs.includes(:cs).collect{|b| b.cs } (this will display c objects in an array in each b object i.e 2D array something like this #[[c1,c2], [c3,c4], ...]. where [c1, c2] belongs to b1
5) a.bs.includes(:cs).collect{|b| b.cs.collect(&:method_name)} (this will put the method names in array. you will see arrays in array because of bs has many cs. each single array inside big array represent one b
6) a.bs.includes(:cs).collect{|b| b.cs.collect(&:method_name)}.flatten.compact (This will make all 2D arrays in single array. read flatten and compact concept.)