这是我提出的最后一个问题的后续行动:{{3}}。该代码是:
@ordered_users = User.all.sort{|a,b| b.followers.count <=> a.followers.count}
我希望完成的是获取有序用户并获得前100名,然后随机选择其中的5个。有没有办法实现这一目标?
感谢。
答案 0 :(得分:6)
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名用户。
答案 1 :(得分:1)
User.all.sort
可以“潜在地”在长期内造成一些问题,具体取决于总用户数量,以及资源的可用性,特别是计算机内存,更不用说它会慢得多,因为你'在.followers.count
块内调用2x sort
,实际上调用了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
,.order
和.limit
都将SQL字符串查询扩展为一个字符串,然后执行该SQL字符串,最后运行.sample(5)
(不是SQL已经了,但此时已经只是一个普通的ruby方法了),最终产生了你需要的结果。答案 2 :(得分:1)
我强烈建议在用户模型上使用计数器缓存,以保留关注者的数量。
这会对添加或删除关注者产生非常小的性能影响,并在执行排序时大大提高性能:
a1 G
a2 T
a3 C
如果您想通过关注者计数排名前n位的用户,或者找不到关注者的用户,那么这一点尤为明显。
0 a1 G
0 a2 T
0 a3 C
此方法将使用User.order(followers_count: :desc)
胜过其他人。在User.order(followers_count: :desc).limit(100).sample(5)
上添加索引以获得最佳效果。