【问题标题】:ActiveRecord select attributes without AR objectsActiveRecord 选择没有 AR 对象的属性
【发布时间】:2010-02-18 12:00:06
【问题描述】:

我有一个包含许多行的表,我只需要某些行的 ID。 慢的方法是调用

SomeARClass.find(:all, :conditions => {:foo => true}, :select => :id)

这将返回 AR 对象...

有没有办法在一个类上调用一个 select 并让它返回一个普通的旧 ruby​​ 数据结构。像这样的:

SomeARClass.select(:id, :conditions => {:foo => true})
-> [1,2,3]

【问题讨论】:

    标签: mysql ruby-on-rails activerecord


    【解决方案1】:
    ActiveRecord::Base.connection.select_all(sql)
    

    SomeARClass.connection.select_all(sql)
    

    这就是你想要使用的。它返回一个哈希数组。不过应该谨慎使用。手工编码的 sql 是 ActiveRecord 用来替代的。我只在构建和返回 AR 对象太慢的真正性能关键领域使用。

    【讨论】:

    • 改用 SomeARClass.pluck(:attribute)。
    【解决方案2】:

    pluck 方法正是您想要的,而不会影响 SQL 的不良做法:

    SomeARClass.where(:foo => true).pluck(:id)
    

    我相信这应该是选择的答案!

    【讨论】:

      【解决方案3】:

      我认为没有像 SomeARClass.select(:id, :conditions => {:foo => true}) 这样的东西,但你有两个选择

      1. SomeARClass.find(:all, :conditions => {:foo => true}, :select => :id).map(&:id)
        #=> [1,2,3,4]
        
      2. id_hash = ActiveRecord::Base.connection.select_all('select id from tablename')
        #=>  [{"id"=>"1"}, {"id"=>"2"}, {"id"=>"3"}, {"id"=>"4"}]
        
        id_hash.map(&:values).flatten
        #=>  ["1", "2", "3", "4"]
        

      第二个选项只返回一个哈希值而不是活动记录对象,但它看起来有点hackish。

      【讨论】:

        【解决方案4】:

        简答:

        注意事项:

        pluckselect_all 之间存在细微差别:

        如果您 pluck 数据 - ActiveRecord 将数据映射到 Ruby 对象,例如日期、枚举、 模型等,它可能与您的预期不同。

        你可以注意到下面的结果是一个字符串:

        2.5.1 :001 > ActiveRecord::Base.connection.select_all("select created_at from some_ar_class where id = 1 limit 1").rows.first
           (0.6ms)  select created_at from some_ar_classes where id = 1 limit 1
         => ["2018-10-01 01:12:31.758161"]
        

        pluck 返回日期

        2.5.1 :002 > SomeARClass.where(id: 1).pluck(:created_at).first.class
           (0.4ms)  SELECT "some_ar_classes"."created_at" FROM "some_ar_classes" WHERE "some_ar_classes"."id" = $1  [["id", 1]]
         => ActiveSupport::TimeWithZone
        

        同样的情况也发生在 Enums(数据库中为 int,但 :symbols 在 Ruby 中)

        所有这些解析/映射操作也需要时间。这不是很多,但仍然。因此,如果您要求以最快的方式获取数据 - 它绝对是带有 connection.select_all 的原始 sql 查询,但在极少数情况下您可以获得显着的性能提升。

        所以我的建议是使用pluck

        【讨论】:

          猜你喜欢
          • 2016-05-29
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-01-07
          • 2017-09-20
          相关资源
          最近更新 更多