Random 什么';这是';轨道4路';找到一些随机记录的方法?
Random 什么';这是';轨道4路';找到一些随机记录的方法?,random,ruby-on-rails-4,Random,Ruby On Rails 4,User.find(:all,:order=>“RANDOM()”,:limit=>10)是我在Rails 3中的方式 User.all(:order=>“RANDOM()”,:limit=>10)是我认为Rails 4会这样做的,但这仍然给了我一个弃用警告: DEPRECATION WARNING: Relation#all is deprecated. If you want to eager-load a relation, you can call #load (e.g. `Post.w
User.find(:all,:order=>“RANDOM()”,:limit=>10)
是我在Rails 3中的方式
User.all(:order=>“RANDOM()”,:limit=>10)
是我认为Rails 4会这样做的,但这仍然给了我一个弃用警告:
DEPRECATION WARNING: Relation#all is deprecated. If you want to eager-load a relation, you can call #load (e.g. `Post.where(published: true).load`). If you want to get an array of records from a relation, you can call #to_a (e.g. `Post.where(published: true).to_a`).
您需要使用
order
和limit
方法。您可以去掉所有的
对于PostgreSQL和SQLite:
User.order("RANDOM()").limit(10)
或者对于MySQL:
User.order("RAND()").limit(10)
由于随机函数可能会因不同的数据库而改变,我建议使用以下代码:
User.offset(rand(User.count)).first
当然,这只有在您只查找一条记录时才有用
如果你想得到更多,你可以这样做:
User.offset(rand(User.count) - 10).limit(10)
-10
是为了确保在rand返回的数字大于count-10的情况下获得10条记录
请记住,您将始终获得10条连续记录。我认为最好的解决方案是在数据库中随机排序。
但若您需要避免数据库中的特定随机函数,可以使用pulk
和shuffle
方法
有一项记录:
User.find(User.pluck(:id).shuffle.first)
User.where(id: User.pluck(:id).sample(10))
对于多个记录:
User.find(User.pluck(:id).shuffle.first)
User.where(id: User.pluck(:id).sample(10))
对于MYSQL,这对我来说很有用:
User.order("RAND()").limit(10)
这里有一个快速的解决方案。。目前使用它的记录超过150万条,性能良好。最好的解决方案是缓存一个或多个随机记录集,然后使用后台工作程序以所需的时间间隔刷新它们
创建了随机记录\u helper.rb
文件:
module RandomRecordsHelper
def random_user_ids(n)
user_ids = []
user_count = User.count
n.times{user_ids << rand(1..user_count)}
return user_ids
end
这比.order(“RANDOM()”).limit(10)
方法快得多-我将加载时间从13秒缩短到500毫秒。我建议将其作为一个范围,因为您可以链接它:
class User < ActiveRecord::Base
scope :random, -> { order(Arel::Nodes::NamedFunction.new('RANDOM', [])) }
end
User.random.limit(10)
User.active.random.limit(10)
class用户{order(Arel::Nodes::NamedFunction.new('random',[])}
结束
用户.随机.限制(10)
用户.活动.随机.限制(10)
虽然不是最快的解决方案,但我喜欢以下简洁:
User.id.sample(10)
.ids
方法生成一个用户ID数组,并且.sample(10)
从该数组中选择10个随机值。强烈建议将此gem用于随机记录,它是专为具有大量数据行的表设计的:
除此之外,所有其他答案在大型数据库中的性能都很差:
quick_random_仅记录成本4.6ms
总计
接受的答案User.order('RAND()).limit(10)
cost733.0ms
offset
进近成本245.4ms
总计
User.all.sample(10)
进近成本573.4ms
注意:我的表只有120000个用户。你拥有的记录越多,表现的差异就越大
更新:
在具有550000行的表上执行
Model.where(id:Model.pull(:id).sample(10))
cost1384.0ms
gem:quick\u random\u记录
仅成本6.4ms
总计
你可以在记录上调用.sample
,比如:User.all.sample(10)
对@maurimirandaUser.offset(rand(User.count))的回答。首先,不适合我们需要得到10条随机记录,因为User.offset(rand(User.count)-10)。限制(10)
将从随机位置返回10条记录的序列,它们不是“随机总计”,对吗?所以我们需要调用该函数10次,得到10个“随机总计”
除此之外,如果随机函数返回高值,则偏移量也不好。如果您的查询看起来像offset:10000和limit:20,那么它将生成10020行并丢弃前10000行,
这是非常昂贵的。因此,调用10倍偏移量。限制是无效的
所以我认为,如果我们只想得到一个随机用户,那么user.offset(rand(user.count))。首先可能更好(至少我们可以通过缓存user.count来改进)
但是如果我们想要10个或更多的随机用户,那么User.order(“RAND()”).limit(10)
应该更好。只是一个简短的说明,我必须使用:User.order(“RAND()”).limit(10)
,因为我使用的是MySQL数据库。注意,这是O(n^2),对于任何大于几行的表来说都是不可接受的。请参阅下面@maurimiranda的.offset(rand())方法,以了解此线程中唯一合理的解决方案。User.order(“RANDOM()”).limit(10)
在Postrgres和Rails 5上对我有效。对于来自Rails 5.2+的任何人,你应该在Arel.sql()
中包装“RANDOM()”或“rand()”,因为它不在安全值列表中。但是,我想这对您来说是安全的。一个Arel.sql示例User.order(Arel.sql('random()')).limit(10)
+1不仅是offset
方法比公认的答案更通用,而且在有大量记录时速度更快。这是因为orderbyrandom()LIMIT$1
将对整个表进行排序,然后选择前n项。排序操作可能是O(n*log n)
,对一个大表进行排序不仅会读取该表,还包括读取和写入临时文件。这对我来说很有效,而User.order(“RANDOM()”)。limit(10)
则没有;它总是返回相同的记录。我使用的是Postgresql数据库,运行的是Rails 5。如果问题是特定于查找随机记录,那么这将是正确的答案。但问题是,一般来说,如何找到随机记录。随机查找一组行实际上并不相同。请注意,您的表不能有delete记录,否则ID不在seq中。它应该是User.offset(rand(User.count-10))。limit(10)
而不是rand(User.count)-10
,否则您可能会得到负索引,这将引发一个PG::InvalidRowCountInResultOffsetClause