Rails为高级用户选择一个随机列表

时间:2018-01-26 02:00:30

标签: sql ruby-on-rails ruby activerecord random

在我的rails应用程序中,我有用户和列表。这些列表属于用户。列表包含user_id,其中包含正在创建列表的用户ID。

用户可以是高级用户,黄金用户或白银用户。

我想要的是每个高级用户,选择一个随机列表以显示在高级列表中。

我可以在O(n ** 2)时间或n + 1查询中执行以下操作:

users_id = User.where(:role => "premium").pluck[:id]
final_array = Array.new
users_id.each do |id|
  final_array << Listing.where(:user_id => id).sample(1)
end
final_array

有更好的方法吗?

3 个答案:

答案 0 :(得分:1)

你可以试试这个:

listings = Listing.select(
  <<~SQL
    DISTINCT ON (users.id) users.id, 
    listings.*, 
    row_number() OVER (PARTITION BY users.id ORDER BY random())
  SQL
)
  .joins(:user)
  .includes(:user)
  .where(users: { role: :premium })

它为每个高级用户提供随机列表。

它产生对db的唯一请求,并且它不会为获取列表的用户提出额外请求,因此您可以自由地执行以下操作:

listings.each do |listing|
  p listing.user
end    

答案 1 :(得分:0)

random_user_listings = []

User.includes(:listings).where(role: "premium").find_each do |user|
  random_user_listings << user.listings.sample(1)
end

random_user_listings

答案 2 :(得分:-1)

要避免N + 1查询,您需要将它们组合起来,执行一次查询,如下所示:

list = Listing.includes(:user).where(:role => "premium").sample(1)

随意处理列表而不是列表。因为现在你正在处理变量,而不是查询。

ids = list.pluck(:user_id).uniq

像上面一样获取id的数组并像你一样做进一步的步骤(但是有list,而不是Listing) 需要注意的是,当你处理模型时,你正在处理QUERY。避免在循环语句中执行此操作。