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



在我的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

有没有更好的方法

你可以试试这个:

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    
random_user_listings = []
User.includes(:listings).where(role: "premium").find_each do |user|
  random_user_listings << user.listings.sample(1)
end
random_user_listings

要避免 N+1 查询,您需要将它们组合在一起,像这样执行一次查询:

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

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

ids = list.pluck(:user_id).uniq

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

最新更新