随机化列表中的选择100

时间:2017-07-11 18:15:38

标签: ruby-on-rails ruby

这是我提出的最后一个问题的后续行动:{{3}}。该代码是:

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

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

感谢。

3 个答案:

答案 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,并结合使用takesample来获得前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) 上添加索引以获得最佳效果。