2014-02-12 82 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

相关问题