我有一个包含用户和工作的招聘系统。
他们之间存在着一种关系:通过潜力。
这基本上允许管理员了解用户适合工作的可能性
要做到这一点,我有一个after_create和一个after_save事件,如此 -
class User < ActiveRecord::Base
after_create :create_potentials
after_save :set_potentials
private
def create_potentials
Job.all.each do | job |
potential = Potential.new
potential.job_id = job.id
potential.user_id = self.id
potential.save!
end
end
def set_potentials
self.potentials.each do |potential|
potential.level = potential.find_potential
potential.save!
end
end
这让我很担心。首先,我使用整个模型只是为了一个属性,“潜在”,这似乎有点古怪。
第二个是在创建用户之后,我正在为总工作量创建潜力。
目前,这些工作相对较少(即30岁以下),但这是很多潜在的计算任务。
after_create和after_save事件是否可以异步运行?
答案 0 :(得分:1)
您可以使用像延迟作业这样的Gem来异步运行方法。
https://github.com/collectiveidea/delayed_job
正如您所说,优化问题的答案可能取决于可能存在多少工作,用户和“潜力”。正确的方法还取决于您是否需要使用SQL查询它们,或者是否可以动态计算它们。
通过关联创建潜力,可以略微缩短您当前的关联代码。如果您决定为每个Potential
为每个User
创建一个Job
,则您需要使用find_each来避免一次将每个作业加载到内存中。
Job.find_each { |job| job.potentials.create!(user_id: self.id) }
答案 1 :(得分:1)
考虑插入/更新逻辑的简单程度以及可能无法执行任何ruby方法,您可能需要考虑通过数据库显式执行此操作。
例如,您的create_potentials
类似于:
insert into potentials select :user_id, id from jobs
其中:user_id
作为查询参数传递,并以类似的方式处理set_potential
(嵌套查询可能在update语句中)。
在某些时候,您可能希望将此逻辑移动到其中一个https://www.ruby-toolbox.com/categories/Background_Jobs中,或者如果逻辑变得复杂,甚至可以回退到在ruby中实现这两个简单方法,
但是现在最简单和最不适合的方法似乎只是使用SQL,跳过后台队列并让数据库处理这个。
此外,无论您采用哪种方式,如果您的项目启动,那么潜在的表看起来会像爆炸一样大小,所以请考虑您的作业架构在富文档模型中的适用程度(请参阅http://www.youtube.com/watch?v=PIWVFUtBV1Q和http://railscasts.com/episodes/238-mongoid?view=asciicast)
根据您的其他设置,您可能会发现它比传统数据库更适合您的需求
答案 2 :(得分:0)
根据您的Qsn,for every new user created. Entries are made into potential table for each job id along with the user_id.
和
更新用户条目potential level is being updated for all the potential table entries for that user which equals total no of jobs present.
如果您正在为用户寻找实时更新,则需要跳过cron部分并实现逻辑以减少查询次数。如果这不是限制那么 建议使用cron作业来处理它,使用redis / resque来处理after_create和after_save任务。创建或更新任何用户时,请执行任务,这些作业将由正在运行的redis服务器处理。
正如doctororange的回答中所建议的那样,如果您想定期处理任务而不管用户表的任何变化,也可以查看延迟的工作。