Sql Rails 3--获取具有不同未知值的最新记录
数据库里有一个模型。该模型有3个关键点: 在、类型、键处创建 创建的时间是时间戳 类型是已知的枚举。 密钥遵循约定,但通常是未知和非唯一的。 对于给定的类型和键组合,可能有数百条记录,而且这些记录可能不小。我尽量避免从数据库中加载它们 问题是要高效地查找对象的最新版本,而不必删除旧版本。我想从数据库中获取某一类型的每个键的最新记录,但我不知道这些键是什么。查询是,我给出一个类型,最后得到一个对象散列[key=>object],其中我为散列选择的对象是最新创建的对象,最新创建的值是该键类型对 我的第一个想法是在记忆中这样做Sql Rails 3--获取具有不同未知值的最新记录,sql,ruby-on-rails-3,activerecord,Sql,Ruby On Rails 3,Activerecord,数据库里有一个模型。该模型有3个关键点: 在、类型、键处创建 创建的时间是时间戳 类型是已知的枚举。 密钥遵循约定,但通常是未知和非唯一的。 对于给定的类型和键组合,可能有数百条记录,而且这些记录可能不小。我尽量避免从数据库中加载它们 问题是要高效地查找对象的最新版本,而不必删除旧版本。我想从数据库中获取某一类型的每个键的最新记录,但我不知道这些键是什么。查询是,我给出一个类型,最后得到一个对象散列[key=>object],其中我为散列选择的对象是最新创建的对象,最新创建的值是该键类型对 我的
# 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中的关键字?我会使用一个单独的表,在一个单独的表中记录最新记录的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
您需要有一个关于LatestModelLookuptype、key和LatestModelLookuptype的索引
因此,当您需要按键查询某个类型的最新记录时,您必须执行以下操作:
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]的新记录时才会更改
编辑:条件已反转