假设我的数据库中有一个用户模型,每个用户的高度和重量已经输入。现在我想在用户表中添加一个BMI列,根据每个现有用户的权重和高度计算。如果我有一百万用户,那么最有效的方法是什么?
P.S
我尝试添加一个在调用时在本地运行脚本的rails路由,但发现它需要很长时间。我不认为我可以使用rails控制台,因为它需要一个复杂的方法。
答案 0 :(得分:1)
你可以使用update_all,这个更新通过数据库NOT循环遍历所有记录 api documentation for update_all
User.update_all('bmi = height * weight')
答案 1 :(得分:0)
首先,您需要迁移才能添加列,但不要设置默认值(设置默认值可能需要很长时间才有大量记录)
add_column:some_attribute,:string
在列之后,您需要回填它。
使用find_each
。无论您做什么,1,000,000名用户都需要一些时间来处理。使用find_each
确保它们一次只能实例化1,000个。
User.find_each do |user|
num = user.height * user.width # or whatever you need to figure out here
user.update_attributes(some_attribute: num)
end
您可以设置一个终结点find_each
,但实际上,您最好通过控制台运行它。我使用screen
,因为它有可能是一个长期运行的过程。
您可以将其放入迁移文件中,但对于是否在迁移中操纵数据的最佳做法存在不同的意见。
答案 2 :(得分:-1)
因此,如果您想为每个现有用户添加BMI,最好的方法是创建rake task
,您可以在其中添加用于更新该列的逻辑。
假设您已将新列bmi
添加到用户模型(整数),那么您需要rake任务:
namespace :user do
task :bmi_calculator => 'environment' do
User.find_each do |user|
bmi = user.height/user.weight (I'm not sure about computation)
user.update_attribute(bmi: bmi)
end
end
end
然后您可以随时运行此任务(rake user:bmi_calculator
)!另外,我的建议是使用一些cron作业来完成这种任务,在午夜流量不是那么大的时候自动运行。
干杯