0

的大小我有以下查询:的ActiveRecord_Relation对象

User.joins(:posts).group('users.id').having('count(user_id) > 1') 

返回类是User::ActiveRecord_Relation

如果我对它调用.size,它会返回一个散列。如果我拨打.size.size,我会得到正确的尺寸。

这真的是我应该如何获得ActiveRecord_Relation的大小,否则正确的方式如何呢?

回答

1

你叫group方法,这就是为什么第一个.size呼叫返回散列。
比方说,你已经调用size第一次,当下面的哈希:

hash = {106=>1, 171=>1, 79=>1, 66=>1, 160=>3, 73=>1, 182=>1, 165=>1, 97=>7, 116=>1} 

然后,你需要从哈希和所有值:

hash.values.reduce(:+) 
=> 18 
+0

你会说,'.size.size'是必经之路如果我想知道返回的哈希包含多少对,那么去吧? –

+0

是的,没错。 – iskvmk

1

重要的是要了解为什么你的哈希,当你请在这里致电#size

#size将执行SELECT COUNT(*)查询是否尚未加载关联。这相当于拨打#count。所以你得到一个散列。

但是如果关联已经被加载到内存中,#size将不会执行任何附加查询,但会获得关联的长度。在这种情况下,散列的长度。请尝试以下控制台:

query = User.joins(:posts).group('users.id').having('count(user_id) > 1'); #don't load the association 
query.size # => hash 
query.size # => length of the previous hash 

因此,这不是一个好主意,依靠此链接#size,除非你确信该协会将不会被此之前加载。相反,使用#length此:

User.joins(:posts).group('users.id').having('count(user_id) > 1').length # => integer 

#length不执行额外的查询,而且将永远加载整个联想到内存中,因此这是一个有点慢,是饿了。但在实践中,除非您加载大量记录,否则通常不会成为问题。

顺便说一句,如果你想要的是找到超过一个职位的用户数量,有没有需要#join

Post.group('user_id').having('count(user_id) > 1').length 
+0

非常感谢您的解释。两件事情,调用'query.size'两次并没有改变输出,你对最后一行的建议对我来说并不奏效。 “ActiveRecord :: StatementInvalid:PG :: GroupingError:错误:列”posts.id“必须出现在GROUP BY子句中或用于聚合函数中” –

+1

对于控制台中的示例,您需要确保'query' isn在调用第一个'#size'之前先加载(不要忘记第一行末尾的分号,以防止导轨加载并确保它之前没有加载)。 最后的代码在MySQL中工作。对于PostgreSQL,您可能希望使用Post.select(:id,:user_id).group('user_id')。having('count(user_id)> 1')。length – EJ2015

相关问题