2014-02-12 90 views
16

我在我的Rails應用程序創建如果記錄不存在

class Contact < ActiveRecord::Base 
    belongs_to :survey, counter_cache: :contact_count 
    belongs_to :voter 
    has_many :contact_attempts 
end 

class Survey < ActiveRecord::Base 
    has_many :questions 
    has_many :contacts 
end 

class Voter < ActiveRecord::Base 
    has_many :contacts 
end 

的聯繫由voter_id和survey_id的3款車型。我的應用程序的邏輯是,在任何給定的調查中,只能有一個選民聯繫人。

現在我正在使用下面的代碼來執行這個邏輯。我在聯繫人表中查詢與給定的voter_id和survey_id匹配的記錄。如果不存在,則創建它。否則它什麼都不做。

if !Contact.exists?(:survey_id => survey, :voter_id => voter) 
    c = Contact.new 
    c.survey_id = survey 
    c.voter_id = voter 
    c.save 
end 

顯然這需要一個select和insert插入查詢來創建1個潛在的聯繫人。當我一次添加潛在數千個聯繫人時。

現在我正在使用Resque來允許在後臺運行並遠離ui線程。我能做些什麼來加快速度,並提高效率?

+3

如果你一次添加十萬,爲什麼不與BULK INSERT或其他一些做AR之外的機制? –

回答

15

你應該首先添加數據庫指數迫使這個條件的最低水平地:

add_index :contacts, [:voter_id, :survey_id], unique: true 

那麼你應該在一個ActiveRecord級別添加一個獨特的驗證:

validates_uniqueness_of :voter_id, scope: [:survey_id] 

然後contact.save將聯繫人是否存在指定的投票和調查返回false

更新:如果您創建索引,那麼唯一性驗證將運行得非常快。

+0

哪裏有:contact_id進場? – gsueagle2008

+0

對不起,這是我的錯誤,已經更新 –

3

如果你讓MySQL來處理它會更好。

創建遷移和添加複合唯一鍵survey_id, voter_id

add_index :contact, [:survey_id, :voter_id], :unique=> true 

現在

Contact.create(:survey_id=>survey, :voter_id=>voter_id) 

將創造新的紀錄只有當不存在重複。

19

你可以做到以下幾點:

Contact.where(survey_id:調查顯示,voter_id:選民).first_or_create

相關問題