代码之家  ›  专栏  ›  技术社区  ›  Daniel Vandersluis

从ActiveRecord模型获取ID列表的最佳实践

  •  4
  • Daniel Vandersluis  · 技术社区  · 15 年前

    我有一个ActiveRecord模型 Language ,列 id short_code (还有其他列,但与此问题无关)。我想创建一个方法,它将得到一个短代码列表,并返回一个ID列表。我不关心关联,我只需要得到一个看起来像[1,2,3,…]的数组。

    我的第一个想法是做一些像

    def get_ids_from_short_codes(*short_codes)
      Language.find_all_by_short_code(short_codes.flatten, :select => 'id').map(&:id)
    end
    

    但我不确定这是否是不必要的浪费时间/内存/处理。

    我的问题是双重的:

    1. 有没有一种方法可以运行只返回某个表列的数组而不实例化对象的ActiveRecord find?
    2. 如果是这样,那么收集一个长度数组是否值得呢? n 而不是实例化 n 激活记录对象?

    注意,为了我的特定目的, n 大约是200。

    6 回复  |  直到 11 年前
        1
  •  6
  •   Phil    15 年前

    老实说,对于200张唱片,我不担心。当您达到2000、20000或200000条记录时,您可以担心优化。

    确保在表中索引了短代码。

    如果您仍然关心性能,请查看development.log并查看该特定调用的数据库编号。您可以调整查询,并在日志中查看它如何影响性能。这应该给你一个粗略的性能估计。

        2
  •  7
  •   Community CDub    8 年前

    在Rails 3.x中,您可以使用 pluck 方法,它从请求的字段返回值,而不实例化对象来保存这些值。

    这将为您提供一个ID数组:

    Language.where(short_code: short_codes.flatten).pluck(:id)
    

    我应该提到,在Rails3.x中,一次只能提取一列,但在Rails4中,可以通过多个列进行提取。

    顺便说一下,这是 similar answer 到A similar question

        3
  •  5
  •   alex.zherdev    15 年前

    同意前面的答案,但是如果你必须这么做,你可以试试这个。

    sql = Language.send(:construct_finder_sql, :select => 'id', :conditions => ["short_code in (?)", short_codes])
    Language.connection.select_values(sql)
    

    虽然有点难看,但它不会创建内存中的对象。

        4
  •  5
  •   Przemek Wroblewski    15 年前

    如果使用关联,则可以直接从ActiveRecord获取原始ID。 如。:

    class User < ActiveRecord::Base
      has_many :users
    end
    
    irb:=> User.find(:first).user_ids
    irb:>> [1,2,3,4,5]
    
        5
  •  3
  •   Ben Hughes    15 年前

    菲尔说得对,但如果你真的发现这是个问题的话。您可以将原始SQL查询发送到数据库,并在ActiveRecord下面的级别工作。这对于类似的情况很有用。

    ActiveRecord::Base.connection.execute("SQL CODE!")
    

    在诉诸于此之前,首先对代码进行基准测试。

        6
  •  0
  •   John Topley    15 年前

    这真的是一个选择的问题。

    是否过度杀伤,激活记录为 想象上的 给你对象,因为它是一个ORM。正如本所说,如果不需要对象,请使用原始SQL。