Как добавить лимит в группу по запросу в рельсах? - PullRequest
2 голосов
/ 06 ноября 2019

Я хочу получить 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)

Ответы [ 4 ]

3 голосов
/ 06 ноября 2019

Как то так?

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

1 голос
/ 06 ноября 2019

Если данные не слишком велики, вы можете сделать это так:

Vote.where(votable_id: @comments_ids, votable_type: 'Comment')
    .select(:votable_id, :user_id)
    .group_by(&:votable_id)
    .transform_values { |v| v.take(10) }
0 голосов
/ 06 ноября 2019
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, где raw sql не будет разрешен в запросах. Ранее я использовал бы .order('COUNT(votable_id) DESC'), но это выдает ошибки и будет запрещено в Rails 6

0 голосов
/ 06 ноября 2019

Не могу вспомнить активную запись или способ SQL сделать это. Но ниже приведено чистое решение Ruby: для ruby ​​2.4 и выше вы можете использовать Hash # transform_values ​​для результата хеширования group_by, например, так (продолжая ваш запрос):

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...