我有一个包含2000个条目的列car_details
,每个条目都是一个如下所示的信息哈希:
{"capacity"=>"0",
"wheels"=>"6",
"weight"=>"3000",
"engine_type"=>"Diesel",
"horsepower"=>"350",
"fuel_capacity"=>"35",
"fuel_consumption"=>"30"}
有些车有更多细节,有些车更少。我希望在每辆拥有该密钥的汽车上将"fuel_consumption"
密钥重命名为"mpg"
。
答案 0 :(得分:1)
据我所知,没有简单的方法可以用原始SQL一起更新数据表中的序列化列。我能想到的最好的方法就是做一些事情:
Car.find_each do |car|
mpg = car.car_details.delete("fuel_consumption")
car.car_details["mpg"] = mpg if mpg
car.save
end
这假设您使用的是Active Record,而您的模型被称为“Car”。
答案 1 :(得分:1)
好吧,之前的回答会生成2000个请求,但您可以使用REPLACE
函数。 MySQL和PostgreSQL都有,所以它会像:
Car.update_all("car_details = REPLACE(car_details, 'fuel_consumption', 'mpg')")
查看条件的update_all
方法。
答案 2 :(得分:1)
@Ivan Shamatov发布的答案非常有效,对于在大型数据库上表现出色尤其重要。
我在jsonb列上的PostgreSQL数据库中进行了尝试。 要使其发挥作用,我们必须同样注意数据类型转换。
例如在这样的User
模型上:
User < ActiveRecord::Base {
:id => :integer,
:created_at => :datetime,
:updated_at => :datetime,
:email => :string,
:first_name => :string,
:last_name => :string,
:custom_data => :jsonb
}
我的目标是在custom_data
jsonb字段中重命名密钥。
例如custom_data
哈希来自以下内容的内容:
{
"foo" => "bar",
"date" => "1980-07-10"
}
收件人:
{
"new_foo" => "bar",
"date" => "1980-07-10"
}
对于所有用户,存在我数据库中的记录。
我们可以执行以下查询:
old_key = 'foo'
new_key = 'new_foo'
User.all.update_all("custom_data = REPLACE(custom_data::text, '#{old_key}'::text, '#{new_key}'::text)::jsonb")
这只会替换jsonb哈希中的目标键(old_key),而不会更改哈希值或其他哈希键。
请注意::text
和::jsonb
类型的转换!