Rails模型 - 更新JSON中的嵌套键/值

时间:2022-01-02 23:08:47

I have a model with the following table format:

我有一个具有以下表格格式的模型:

string  "name"
integer "line_id"
json    "filters"

Where the filters field contains a json object with nested keys. I want to modify a specific key without overwriting the rest of the json.

其中filters字段包含具有嵌套键的json对象。我想修改一个特定的键而不覆盖其余的json。

Currently, the json object stored in filters looks like

目前,存储在过滤器中的json对象看起来像

{
  "ext": {"name": "filter", "id": 3},
  "int": {"name": "numb", "id": 1}
}

I'm trying to update int.name's value to "remove" without modifying the rest of the json object.

我正在尝试将int.name的值更新为“remove”而不修改json对象的其余部分。

If I do the following, it'll simply overwrite the entire json object instead of modifying that specific key:

如果我执行以下操作,它将简单地覆盖整个json对象,而不是修改该特定键:

Model.where("filters->>'int'->>'name' IS NOT NULL").update(
  filters: {
    int: {
      name: "remove"
    }
  }
)

How can I simply update that one key with the path int.name while keeping the rest of the attributes the same?

如何使用路径int.name更新那一个密钥,同时保持其余属性相同?

2 个解决方案

#1


2  

which version of rails are you using? if you are using rails 5, you should be able to

您使用的是哪个版本的导轨?如果你使用的是rails 5,你应该可以

m = Model.where("filters->>'int'->>'name' IS NOT NULL").first
m.filters['name'] = 'remove'
m.save

this will leave the existing hash keys in place.

这将保留现有的哈希键。

I think with rails 4, you need a json serializer on the field, but should work the same way once you have the serializer, i believe.

我认为使用rails 4,你需要在现场使用json序列化器,但是一旦你拥有了序列化器,它应该以相同的方式工作,我相信。

#2


0  

How about something like this

这样的事情怎么样?

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)

I have never used a json column so I am unsure if the anticipated value is meant to be JSON or a Hash that will be converted to JSON before insertion but the update statement will be akin to

我从来没有使用过json列,因此我不确定预期的值是JSON还是在插入之前将转换为JSON的Hash,但更新语句将类似于

Model.update([1],[{
         "ext"=> {"name"=> "filter", "id"=> 3},
         "int"=> {"name"=> "remove", "id"=> 1}
       }])

This uses ActiveRecord::Relation#update where the first Array is the ids to update and the second Array is the new values to associate with those ids.

这使用ActiveRecord :: Relation#update,其中第一个Array是要更新的ID,第二个Array是与这些ID关联的新值。

#1


2  

which version of rails are you using? if you are using rails 5, you should be able to

您使用的是哪个版本的导轨?如果你使用的是rails 5,你应该可以

m = Model.where("filters->>'int'->>'name' IS NOT NULL").first
m.filters['name'] = 'remove'
m.save

this will leave the existing hash keys in place.

这将保留现有的哈希键。

I think with rails 4, you need a json serializer on the field, but should work the same way once you have the serializer, i believe.

我认为使用rails 4,你需要在现场使用json序列化器,但是一旦你拥有了序列化器,它应该以相同的方式工作,我相信。

#2


0  

How about something like this

这样的事情怎么样?

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)

I have never used a json column so I am unsure if the anticipated value is meant to be JSON or a Hash that will be converted to JSON before insertion but the update statement will be akin to

我从来没有使用过json列,因此我不确定预期的值是JSON还是在插入之前将转换为JSON的Hash,但更新语句将类似于

Model.update([1],[{
         "ext"=> {"name"=> "filter", "id"=> 3},
         "int"=> {"name"=> "remove", "id"=> 1}
       }])

This uses ActiveRecord::Relation#update where the first Array is the ids to update and the second Array is the new values to associate with those ids.

这使用ActiveRecord :: Relation#update,其中第一个Array是要更新的ID,第二个Array是与这些ID关联的新值。