【问题标题】:Size of an ActiveRecord_Relation objectActiveRecord_Relation 对象的大小
【发布时间】:2017-09-04 21:59:12
【问题描述】:

我有以下疑问:

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

返回的类是User::ActiveRecord_Relation

如果我在上面调用.size,它会返回一个哈希值。如果我调用.size.size,我会返回正确的大小。

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

【问题讨论】:

    标签: ruby-on-rails activerecord rails-activerecord ruby-on-rails-5


    【解决方案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
    

    【讨论】:

    • 非常感谢您的解释。但是有两件事,两次调用query.size 并没有改变输出,而且你在最后一行的建议对我来说也没有奏效。 "ActiveRecord::StatementInvalid: PG::GroupingError: ERROR: column "posts.id" 必须出现在 GROUP BY 子句中或用于聚合函数中"
    • 对于控制台中的示例,您需要确保在调用第一个 #size 之前未加载 query(不要忘记第一行末尾的分号以抑制rails 从加载它并确保它之前没有加载)。最后一个代码在 MySQL 中工作。对于 PostgreSQL,您可能需要使用 Post.select(:id, :user_id).group('user_id').having('count(user_id) > 1').length
    【解决方案2】:

    您调用了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 是要走的路吗?
    猜你喜欢
    • 1970-01-01
    • 2016-02-25
    • 1970-01-01
    • 2010-10-12
    • 2011-11-01
    • 2010-12-05
    • 1970-01-01
    • 1970-01-01
    • 2013-09-26
    相关资源
    最近更新 更多