随机选择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
更容易使用,并结合take
和sample
来获得前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
上添加索引以获得最佳效果。