2011-07-25 5 views
0

私はデータベースにモデルを持っています。で、まあ、タイムスタンプ Rails 3 - 明確で未知の値で最新レコードを取得する

  • タイプが知られている列挙され、

    のcreated_at、タイプ、キー

    • のcreated_at:モデルは、関心のある3つのキーを持っています。
    • キーは慣例に従いますが、一般的には不明で非ユニークです。

    特定のタイプとキーの組み合わせで、数百ものレコードが存在する可能性があり、そのレコードは潜在的に小さくありません。私は可能な限りそれらをデータベースからロードするのを避けようとしています。

    問題は、(古いバージョンを削除することなく)オブジェクトの最新バージョンを効率的に見つけることです。あるタイプの各キーのデータベースから最新のレコードを取得したいのですが、キーの内容がわかりません。クエリは私が型を与えることです、私はハッシュのために選択したオブジェクトがそのキー型のペアを持つ最新のオブジェクト(最新のcreated_at値)であるオブジェクト[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} 
    

    だった。しかし、これは私がスケールとして醜い大きなを取得する予定です。 2番目の考えは、すべてのキーを取得し、すべてのモデルを照会することです。以下のような何か:

    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

    最新のレコードの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]の新しいレコードが追加された場合にのみ変更されます。


    編集:条件付き逆転した

    関連する問題