的大小我有以下查询:的ActiveRecord_Relation对象
User.joins(:posts).group('users.id').having('count(user_id) > 1')
返回类是User::ActiveRecord_Relation
。
如果我对它调用.size
,它会返回一个散列。如果我拨打.size.size
,我会得到正确的尺寸。
这真的是我应该如何获得ActiveRecord_Relation的大小,否则正确的方式如何呢?
的大小我有以下查询:的ActiveRecord_Relation对象
User.joins(:posts).group('users.id').having('count(user_id) > 1')
返回类是User::ActiveRecord_Relation
。
如果我对它调用.size
,它会返回一个散列。如果我拨打.size.size
,我会得到正确的尺寸。
这真的是我应该如何获得ActiveRecord_Relation的大小,否则正确的方式如何呢?
你叫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
重要的是要了解为什么你的哈希,当你请在这里致电#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
非常感谢您的解释。两件事情,调用'query.size'两次并没有改变输出,你对最后一行的建议对我来说并不奏效。 “ActiveRecord :: StatementInvalid:PG :: GroupingError:错误:列”posts.id“必须出现在GROUP BY子句中或用于聚合函数中” –
对于控制台中的示例,您需要确保'query' isn在调用第一个'#size'之前先加载(不要忘记第一行末尾的分号,以防止导轨加载并确保它之前没有加载)。 最后的代码在MySQL中工作。对于PostgreSQL,您可能希望使用Post.select(:id,:user_id).group('user_id')。having('count(user_id)> 1')。length – EJ2015
你会说,'.size.size'是必经之路如果我想知道返回的哈希包含多少对,那么去吧? –
是的,没错。 – iskvmk