【问题标题】:How to add limit in group by query in rails?如何在rails中通过查询添加限制?
【发布时间】:2019-11-06 05:58:21
【问题描述】:

我想获取前 10 名选民的评论并添加分组依据?

示例响应:

1 => [1,2,3,4,5,6,7,8,9,10],
2 => [1,2,3,4]}

投票人数不得超过 10 人。

  create_table "votes", force: :cascade do |t|
    t.integer  "user_id",      limit: 4,   null: false
    t.integer  "votable_id",   limit: 4,   null: false
    t.string   "votable_type", limit: 191, null: false
    t.integer  "weight",       limit: 4
  end

  create_table "comments", force: :cascade do |t|
    t.text     "message",          limit: 16777215,   null: false
    t.string   "type",             limit: 255
    t.integer  "commentable_id",   limit: 4
    t.string   "commentable_type", limit: 191
    t.integer  "user_id",          limit: 4,          null: false
  end

这是我的查询,它返回所有选民。相反,我需要为每条评论返回前 10 名选民。

Vote.where(votable_id: @comments_ids, votable_type: 'Comment').select(:votable_id, :user_id).group_by(&:votable_id)

【问题讨论】:

  • 可以添加模型(投票、评论)和架构文件吗?
  • @SebastianPalma 已添加。
  • @sureshprasanna70 它增加了完成查询的限制,而不是我需要按数组单独分组。
  • 由于您需要按数组限制单个组,我认为您应该尝试在单个模型中使用范围?

标签: mysql sql ruby-on-rails activerecord group-by


【解决方案1】:

这样的?

Vote.group(:user_id).limit(10)

【讨论】:

    【解决方案2】:

    如果数据不是太大,可以这样:

    Vote.where(votable_id: @comments_ids, votable_type: 'Comment')
        .select(:votable_id, :user_id)
        .group_by(&:votable_id)
        .transform_values { |v| v.take(10) }
    

    【讨论】:

      【解决方案3】:
      table = Vote.arel_table
      
      Vote.where(votable_id: @comments_ids, votable_type: 'Comment')
          .select(:votable_id, :user_id)
          .group(:votable_id, :user_id, :id)
          .order('table[:votable_id].count.desc')
          .limit(10)
      

      这应该为您提供前十名投票的列表。如果集合很大,使用带有#group_by 的香草红宝石将需要很长时间。使用 Arel 将避免 Rails 6.0 中不允许在查询中使用原始 sql 的任何重大更改。我以前会使用.order('COUNT(votable_id) DESC'),但这会引发错误,并且在 Rails 6 中会被禁止

      【讨论】:

      • 在这个查询之后得到这个:#<:activerecord_relation:0x3fef7973c168>
      【解决方案4】:

      想不出一个活动记录或 SQL 方式来做到这一点。 但下面是一个纯 Ruby 解决方案: 对于 ruby​​ 2.4 及更高版本,您可以像这样在 group_by 哈希结果上使用 Hash#transform_values(继续您的查询):

      votes = Vote.where(votable_id: @comments_ids, votable_type: 
      'Comment').select(:votable_id, :user_id).group_by(&:votable_id)
      
      top_voters = votes.transform_values do |val|
        voters = val.map(&:user_id)
        freq = voters.reduce(Hash.new(0)) {|h, v| h[v] += 1; h }
        sorted_votes = voters.uniq.sort_by {|elem| -freq[elem] }
        sorted_votes.take(10)
      end
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-02-10
        • 1970-01-01
        • 1970-01-01
        • 2014-07-16
        • 2011-09-08
        • 2014-08-09
        • 2017-04-24
        • 1970-01-01
        相关资源
        最近更新 更多