我有一个具有以下表格格式的模型:
string "name"
integer "line_id"
json "filters"
filters
字段包含带嵌套键的json对象。我想修改一个特定的密钥而不覆盖其余的json。
目前,存储在filters
中的json对象看起来像
{
"ext": {"name": "filter", "id": 3},
"int": {"name": "numb", "id": 1}
}
我正在尝试将int.name
的值更新为"remove"
而不修改json对象的其余部分。
如果我执行以下操作,它只会覆盖整个json对象而不是修改该特定键:
Model.where("filters->>'int'->>'name' IS NOT NULL").update(
filters: {
int: {
name: "remove"
}
}
)
如何只使用路径int.name
更新一个密钥,同时保持其余属性相同?
答案 0 :(得分:2)
您使用的是哪个版本的导轨?如果你使用的是rails 5,你应该可以
m = Model.where("filters->>'int'->>'name' IS NOT NULL").first
m.filters['name'] = 'remove'
m.save
这将保留现有的哈希键。
我认为使用rails 4,你需要在场上使用json序列化器,但是一旦你拥有序列化器,它应该以相同的方式工作,我相信。
答案 1 :(得分:0)
这样的事情
models = Model.where("filters->>'int'->>'name' IS NOT NULL")
.each_with_object({}) do |m,obj|
# credit to mudasobwa for the tap usage
obj[m.id] = {filters: m.filters.tap { |h| h['int']['name'] = 'remove' } }
end
Model.update(models.keys,models.values)
我从未使用过json
列,所以我不确定预期的值是JSON还是Hash
,它会在插入之前转换为JSON,但更新语句类似于
Model.update([1],[{
"ext"=> {"name"=> "filter", "id"=> 3},
"int"=> {"name"=> "remove", "id"=> 1}
}])
这使用ActiveRecord::Relation#update
,其中第一个Array
是要更新的ID,第二个Array
是与这些ID关联的新值。