如果记录不存在则创建

时间:2022-09-25 23:50:47

I have 3 models in my rails app

我的rails应用程序中有3个型号

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

the Contact consists of the voter_id and a survey_id. The Logic of my app is that a there can only be one contact for a voter in any given survey.

联系人由voter_id和survey_id组成。我的应用程序的逻辑是,在任何给定的调查中,选民只能有一个联系人。

right now I am using the following code to enforce this logic. I query the contacts table for records matching the given voter_id and survey_id. if does not exist then it is created. otherwise it does nothing.

现在我使用以下代码来强制执行此逻辑。我在contacts表中查询与给定的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

Obviously this requires a select and a insert query to create 1 potential contact. When I am adding potentially thousands of contacts at once.

显然,这需要select和insert查询来创建1个潜在联系人。当我一次添加可能数千个联系人时。

Right now I'm using Resque to allow this run in the background and away from the ui thread. What can I do to speed this up, and make it more efficient?

现在我正在使用Resque来允许在后台运行并远离ui线程。我该怎么做才能加快速度,提高效率?

4 个解决方案

#1


16  

You should add first a database index to force this condition at the lowest level as possible:

您应该首先添加一个数据库索引,以尽可能将此条件强制为最低级别:

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

Then you should add an uniqueness validation at an ActiveRecord level:

然后,您应该在ActiveRecord级别添加唯一性验证:

validates_uniqueness_of :voter_id, scope: [:survey_id]

Then contact.save will return false if a contact exists for a specified voter and survey.

如果指定选民和调查的联系人存在,那么contact.save将返回false。

UPDATE: If you create the index, then the uniqueness validation will run pretty fast.

更新:如果您创建索引,那么唯一性验证将运行得非常快。

#2


21  

You can do the following:

您可以执行以下操作:

Contact.where(survey_id: survey,voter_id: voter).first_or_create

#3


9  

See if those links can help you.

看看这些链接是否可以帮助您。

Those links are for rails 4.0.2, but you can change in the api docks

这些链接适用于rails 4.0.2,但您可以更改api基座

From the apidock: first_or_create, find_or_create_by
From the Rails Guide: find-or-create-by

从apidock:first_or_create,find_or_create_by来自Rails指南:find-or-create-by

#4


4  

It would be better if you let MySQL to handle it.

如果你让MySQL来处理它会更好。

Create a migration and add a composite unique key to survey_id, voter_id

创建迁移并向survey_id,voter_id添加复合唯一键

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

Now

现在

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

Will create new record only if there is no duplicates.

只有在没有重复的情况下才会创建新记录。

#1


16  

You should add first a database index to force this condition at the lowest level as possible:

您应该首先添加一个数据库索引,以尽可能将此条件强制为最低级别:

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

Then you should add an uniqueness validation at an ActiveRecord level:

然后,您应该在ActiveRecord级别添加唯一性验证:

validates_uniqueness_of :voter_id, scope: [:survey_id]

Then contact.save will return false if a contact exists for a specified voter and survey.

如果指定选民和调查的联系人存在,那么contact.save将返回false。

UPDATE: If you create the index, then the uniqueness validation will run pretty fast.

更新:如果您创建索引,那么唯一性验证将运行得非常快。

#2


21  

You can do the following:

您可以执行以下操作:

Contact.where(survey_id: survey,voter_id: voter).first_or_create

#3


9  

See if those links can help you.

看看这些链接是否可以帮助您。

Those links are for rails 4.0.2, but you can change in the api docks

这些链接适用于rails 4.0.2,但您可以更改api基座

From the apidock: first_or_create, find_or_create_by
From the Rails Guide: find-or-create-by

从apidock:first_or_create,find_or_create_by来自Rails指南:find-or-create-by

#4


4  

It would be better if you let MySQL to handle it.

如果你让MySQL来处理它会更好。

Create a migration and add a composite unique key to survey_id, voter_id

创建迁移并向survey_id,voter_id添加复合唯一键

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

Now

现在

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

Will create new record only if there is no duplicates.

只有在没有重复的情况下才会创建新记录。