ActiveRecord 并没有直接提供随机获取的接口,有以下几种方法可以实现。
初级
Model.all.sample(n)
返回 Model 的所有 records ,浪费带宽,浪费内存,效率奇差,无节操。
进阶
ids = Model.pluck(:id).sample(n)
Model.where(id: ids)
先返回 Model 的所有 records 的 id ,然后随机选择 n 个,再次用 where 请求数据;效率不错,很有节操了。
装逼
数据库本身通常都提供 random 的语句,结合 ActiveRecord 的 order 可以用于获取随机 records :
# mysql
Model.order("RAND()").first(n)
# PostgreSQL and sqlite
Model.order("RANDOM()").first(n)
看起来很牛逼的样子,只需要因此 DB query ,但是违背了 ActiveRecord 的 database-agnostic 原则,而且数据库本身的 RANDOM 实现的效率并不高。
装逼也要有境界
尽管数据库的 random 语句各有不同,但 randumb-Adds ability to pull back random records from Active Record 封装了不同数据库的 random ,如果感兴趣,可以尝试使用这个库。
如果只随机选择一个 record
如果只想随机选择一个 record ,这种方法也是一个可选项:
offset = rand(Model.count)
Model.offset(offset).first
结论
因此,看起来进阶的方法是最靠谱的:
ids = Model.pluck(:id).sample(n)
Model.where(id: ids)
达到了各方面平衡。