随机选择100列表中的选择

这是我提出的最后一个问题的后续问题: 按照关注者数排序用户 。 该代码是:

@ordered_users = User.all.sort{|a,b| b.followers.count a.followers.count}

我希望完成的是获取有序用户并获得前100名, 然后随机选择其中的5个。有没有办法实现这一目标?

谢谢。

 users_in_descending_order_of_followers = User.all.sort_by { |u| -u.followers.count } sample_of_top = users_in_descending_order_of_followers.take(100).sample(5) 

您可以使用sort_by ,它比sort更容易使用,并结合takesample来获得前100名用户和样本5的用户。

User.all.sort可能“潜在地”在长期内造成一些问题,具体取决于总用户数,以及资源的可用性,特别是计算机内存,更不用说因为你打电话给2x会慢一些sort块内的.followers.count ,实质上调用了2xN倍以上的DB查询; N是用户数。 这是因为User.all.sort将立即执行User.all查询,从而将所有User记录提取到内存中,而不是通常的延迟加载的User.all ,直到您(例如使用.each或更好)然而.find_each某个地方)

我建议如下(我将Deekshith的答案扩展到你指向另一个问题的链接):

 User.joins(:followers).order('count(followers.user_id) desc').limit(100).sample(5) 
  • .joins.joins.limit都将SQL字符串查询扩展为一个字符串,然后执行该SQL字符串,最后运行.sample(5) (不再是SQL了!),但已经只是一个普通的ruby方法在这一点上),最终产生你需要的结果。

我强烈建议在User模型上使用计数器缓存来保存关注者的数量。

这会对添加或删除关注者产生非常小的性能影响,并在执行排序时大大提高性能:

 User.order(followers_count: :desc) 

如果您希望通过关注者计数排名前n位的用户,或找到没有关注者的用户,这将特别明显。

 User.order(followers_count: :desc).limit(100).sample(5) 

此方法将使用count(*)超出其他方法。 在followers_count上添加索引以获得最佳效果。