简体   繁体   English

Active Record 更新所有 JSON 字段

[英]Active Record Update All JSON Field

So I have a model Item that has a huge postgresql JSON field called properties .所以我有一个模型Item ,它有一个巨大的 postgresql JSON 字段,称为properties Most of the time this field does not need to be queried on or changed, however we store price in this field.大多数时候不需要查询或更改此字段,但是我们将price存储在此字段中。

I'm currently writing a script that updates this price , but there's only a few unique prices and thousands of Items so in order to save time I have a list of Items for each unique price and I'm attempting to do an update all:我目前正在编写一个更新这个price的脚本,但是只有几个唯一的prices和数千个Items ,所以为了节省时间,我有一个每个唯一priceItems列表,我正在尝试全部更新:

Item.where(id: items).update_all("properties->>'price' = #{unique_price}")

But this gives me:但这给了我:

syntax error at or near "->>"

Is there a way to use update all to update a field in a postgres JSON field?有没有办法使用 update all 来更新 postgres JSON 字段中的字段?

You need to use jsonb_set() function, here is an example :您需要使用jsonb_set()函数,这是一个示例

Item.where(id: items).
     update_all(
       "properties = jsonb_set(properties, '{price}', to_json(#{unique_price}::int)::jsonb)"
     )

This would preserve all values and update only one key.这将保留所有值并仅更新一个键。

Read documentation阅读 文档

You can also do this你也可以这样做

Item.where(id: items).each do |item|
  properties = item.properties
  item.update(properties: properties.merge({
    price: unique_price
  }))
end

The keyword merge will override the value of the key provided with the new value ie unique_price关键字merge将覆盖与新值一起提供的键的值,即 unique_price

Merge documentation is here合并文档在这里

What I came up with based on @Philidor's suggestion is very similar but with dynamic bindings:我根据@Philidor 的建议提出的想法非常相似,但具有动态绑定:

assignment = ["field = jsonb_set(field, '{ name_of_the_key }', ?)", value.to_json]
scope.update_all(scope.model.sanitize_sql_for_assignment(assignment))

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM