Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby-on-rails-4/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Random 什么';这是';轨道4路';找到一些随机记录的方法?_Random_Ruby On Rails 4 - Fatal编程技术网

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)
    cost
    733.0ms
  • offset
    进近成本
    245.4ms
    总计
  • User.all.sample(10)
    进近成本
    573.4ms
  • 注意:我的表只有120000个用户。你拥有的记录越多,表现的差异就越大


    更新:

    在具有550000行的表上执行

  • Model.where(id:Model.pull(:id).sample(10))
    cost
    1384.0ms
  • gem:quick\u random\u记录
    仅成本
    6.4ms
    总计

  • 你可以在记录上调用
    .sample
    ,比如:
    User.all.sample(10)
    对@maurimiranda
    User.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