2015-11-03 63 views
0

我正在創建一個原始的SQL upsert,並且我有一個相當大的ActiveRecord關係數組,我需要將其轉換爲散列。我需要使用我選擇的其中一個參數來鎖定哈希值,以便快速獲得該值。如何將一個ActiveRecord關係數組轉換爲一個散列的參數?

I found this response using as_json我幾乎可以得到我需要的東西,但它不是那樣。

profiles = Profile.all.select(:id, :foo) #returns an array of ActiveRecord Relations 
profiles = profiles.as_json 

息率

{:id => 123, :foo => "bar"} 
{:id => 456, :foo => "baz"} 

但我想是

{123 => "bar", 456 => "baz"} 

我意識到,我可以as_json的結果映射到一個新的哈希,但我必須運行此在幾百萬條記錄上相當頻繁地發生。這也是一個更大的rake任務的一小部分,我想繼續循環所有的記錄到最小。

我之所以這樣做是爲了手動完成這一切,而不是讓ActiveRecord處理它,原因是它最初需要24小時以上才能運行任務,甚至使用activerecord-import也只能加速到12小時。 I chose to go with using raw sql based off the benchmarks made in this blogpost

+0

什麼是你的軌道版本? – Santhosh

+0

我正在使用Rails 4.2.4 – wslater

回答

0

在您profile模型,你可以做到這一點,以獲得您想要的結果:

def self.to_hash 
    Hash[*all.map{|p| [p.id, p.foo]}.flatten] 
    end 

然後,您可以撥打:Profile.select(:id, :foo).to_hash

1

您可以使用select_all方法獲得哈希,而不是ActiveRecord的對象的數組,它速度更快,內存消耗更少。

Profile.connection.select_all("select id, foo from profiles;") 
=> [{"id" => xxx, "foo" => xxx}, {}, .....] 

然後將結果轉換爲您需要的格式。

+0

謝謝!我最終使用了它,速度更快,因此將它映射到我想要的散列並不是一個很大的性能影響。 – wslater

0

我可能會繞過的ActiveRecord和像這樣的東西直接發出聲音的數據從數據庫中的一個哈希:

Profile.connection 
     .execute('select id, foo from profiles') 
     .each_with_object({}) { |row, h| h[row['id'].to_i] = row['foo'] } 

或者更好(IMO),旁路的Rails和Ruby也和你所需要的一切使用SQL,臨時表等在數據庫內進行操作。當您處理大量數據時,最好的辦法是通常完全忽略您的應用程序,並在數據庫中執行所有操作。數據庫在處理大量數據方面非常出色,這就是他們所做的。

2

在Rails4,你可以做

Profile.pluck(:id, :foo).to_h 
相關問題