Rails 3 - 获得具有独特,未知值的最新记录

时间:2011-07-25 03:33:51

标签: sql ruby-on-rails-3 activerecord

我在数据库中有一个模型。该模型有3个感兴趣的键:

created_at,type,key

  • created_at,是,时间戳
  • type是已知的枚举。
  • 键遵循约定,但通常是未知的且非唯一的。

可能有数百条具有给定类型和密钥组合的记录,并且记录可能不小。我试图尽量避免从数据库中加载它们。

问题是有效地找到对象的最新版本(无需删除旧版本)。我想从数据库中获取一个类型的每个键的最新记录,但我不知道键是什么。查询是我给出了一个类型,我最终得到了一个Hash of objects [key =>我为散列选择的对象是具有该键类型对的最新对象(最近的created_at值)。

我的第一个想法是在记忆中做到这一点

 # this is pseudo code, have not compiled
 models = Model.where(:type => :some_type).order("created_at desc")
 result = models.inject(Hash.new) {|r, m| r[m.key] = m unless r.has_key? m.key}

但随着我的扩展,这将变得难看。第二个想法是获取所有密钥然后查询所有模型。类似的东西:

 keys = Model.where(:type => :some_type).select("DISTINCT key").map{|m| m.key }
 result = keys.inject(Hash.new) {|r, k| r[k] = Model.where(:type => :some_type).where(:key => k).order("created_at").last; r }

但是,当我写这段代码时,我一直在思考,必须有更好的方法。这个解决方案会让我在事情发展的过程中对数据库进行大量的查询。在某些时候,无论如何我都必须盖上密钥,所以如果你能建议一个让我限制/分页结果的解决方案,那就更好了。

那么,有没有办法更有效地做到这一点?也许Arel中的魔法搜索参数或SQL中的关键字我已经忘记了?

1 个答案:

答案 0 :(得分:1)

我会使用一个单独的表,在单独的表中记录最新记录的ID,即

class Model
  after_create :update_latest_record

  def update_latest_record
    if latest_model = LatestModelLookup.where(:type => self.type, :key => self.key)
      latest_model.update_attributes(:model_id => self.id)
    else
      LatestModelLookup.create(:type => self.type, :key => self.key, :model_id => self.id)
    end
  end
end

您需要在LatestModelLookup(type, key)(可能是LatestModelLookup(type))上建立索引

因此,当您需要按类型的键查询最新记录时,您必须执行以下操作:

model_ids = LatestModelLookup.where(:type => type).select('model_id').map(&:model_id)
result = Model.find(model_ids).inject({}) { |res, rec| res[rec.key] = rec }

拥有一个单独的表的好处是更新LatestModelLookup上的索引的开销非常低。只有在添加了不同[type, key]的新记录时,索引才会更改。


编辑:条件被颠倒