Rails选择随机记录

时间:2010-09-04 05:34:45

标签: mysql ruby-on-rails ruby

我不知道我是不是只是在这里查找错误的地方或者是什么,但是活动记录是否有检索随机对象的方法?

喜欢什么?

@user = User.random

或者......好吧,因为那个方法不存在是否有一些惊人的“Rails方式”这样做,我似乎总是冗长。我也在使用mysql。

8 个答案:

答案 0 :(得分:39)

我见过的大多数例子最终会计算表中的行数,然后生成一个随机数来选择一行。这是因为诸如RAND()之类的替代方案效率低下,因为它们实际上得到每一行并为它们分配一个随机数,或者我已经读过(我认为这是数据库特定的)。

您可以添加类似我找到的方法here

module ActiveRecord
  class Base
    def self.random
      if (c = count) != 0
        find(:first, :offset =>rand(c))
      end
    end
  end
end

这将使你所使用的任何模型都有一个名为random的方法,它按照我上面描述的方式工作:在表中的行计数内生成一个随机数,然后获取与之关联的行那个随机数。所以基本上,你只做一次你喜欢的提取:)

您还可以查看this rails plugin

答案 1 :(得分:7)

我们发现,对于大型表,偏移在MySql上缓慢运行非常。而不是使用偏移量:

model.find(:first, :offset =>rand(c))

...我们发现以下技术运行速度提高了10倍以上(固定为1):

max_id = Model.maximum("id")
min_id = Model.minimum("id")
id_range = max_id - min_id + 1
random_id = min_id + rand(id_range).to_i
Model.find(:first, :conditions => "id >= #{random_id}", :limit => 1, :order => "id")

答案 2 :(得分:4)

尝试使用Array的sample方法:

@user = User.all.sample(1)

答案 3 :(得分:3)

我会使用命名范围。只需将其添加到用户模型中即可。

named_scope :random, :order=>'RAND()', :limit=>1

虽然随机函数在每个数据库中都不相同。 SQLite和其他人使用RANDOM(),但您需要使用RAND()作为MySQL。

如果您希望能够抓住多个随机行,可以试试这个。

named_scope :random, lambda { |*args| { :order=>'RAND()', :limit=>args[0] || 1 } }

如果您致电User.random,则默认为1,但如果您需要多个,也可以致电User.random(3)

答案 4 :(得分:3)

在Rails 4中,我会扩展ActiveRecord::Relation

class ActiveRecord::Relation
  def random
    offset(rand(count))
  end
end

这样你可以使用范围:

SomeModel.all.random.first # Return one random record
SomeModel.some_scope.another_scope.random.first

答案 5 :(得分:2)

如果您需要随机记录但仅在某些条件下,您可以使用此代码中的“random_where”:

module ActiveRecord
  class Base
    def self.random
      if (c = count) != 0
        find(:first, :offset =>rand(c))
      end
    end

    def self.random_where(*params)
      if (c = where(*params).count) != 0
        where(*params).find(:first, :offset =>rand(c))
      end
    end

  end
end

例如:

@user = User.random_where("active = 1")

此功能对于根据一些其他标准显示随机产品非常有用

答案 6 :(得分:1)

这是从数据库中获取随机记录的最佳解决方案。 RoR提供易于使用的一切。

要从数据库中获取随机记录,请使用示例,以下是带示例的说明。

基于Marc-Andre Lafortune的阵列#sample的后端github.com/marcandre/backports/返回数组中的随机元素或n个随机元素。如果数组为空且n为nil,则返回nil。如果传递了n并且其值小于0,则会引发ArgumentError异常。如果n的值等于或大于0,则返回[]。

[1,2,3,4,5,6].sample     # => 4     
[1,2,3,4,5,6].sample(3)  # => [2, 4, 5]     
[1,2,3,4,5,6].sample(-3) # => ArgumentError: negative array size     
[].sample     # => nil     
[].sample(3)  # => []     

您可以根据您的要求使用条件,如下例所示。

User.where(active:true).sample(5)

它将从用户表

中随机返回5个活动用户

如需更多帮助,请访问:http://apidock.com/rails/Array/sample

答案 7 :(得分:1)

强烈推荐这个gem用于随机记录,这是专为具有大量数据行的表而设计的:

https://github.com/haopingfan/quick_random_records

简单用法:

@user = User.random_records(1).take

所有其他答案在大型数据库中都表现不佳,除了这个gem:

  1. quick_random_records仅花费4.6ms
  2. enter image description here

    1. 接受的答案User.order('RAND()').limit(10)费用为733.0ms
    2. enter image description here

      1. offset进近费用245.4ms
      2. enter image description here

        1. User.all.sample(10)进近费用573.4ms
        2. enter image description here

          注意:我的表只有120,000个用户。您拥有的记录越多,性能差异就越大。

          更新:

          在表格上执行550,000行

          1. Model.where(id: Model.pluck(:id).sample(10))费用1384.0ms
          2. enter image description here

            1. gem: quick_random_records仅花费6.4ms
            2. enter image description here