简体   繁体   English

以 JSONB 格式更新对象数组 PostgreSQL

[英]Update array of objects in JSONB format PostgreSQL

I need to perform two update operations:我需要执行两个更新操作:

  1. update change data from string to bool in first case在第一种情况下将更改数据从字符串更新为布尔值
  2. recreate tag with new name and data based on other tag基于其他标签使用新名称和数据重新创建标签

sample data in jsonb column: jsonb 列中的示例数据:

[
    { "tax": "yes", "tax_percent": 20, "used_when": "after" },
    { "tax": "no", "tax_percent": 20 },
    { "tax_percent": 20, "used_when": "before" }
]

and now:现在:

"tax" value needs to be updated from yes -> true, no OR null (not exists) means -> false “税”值需要从 yes -> true、no 或 null(不存在)更新意味着 -> false

"used_when" needs to be updated to "using" and if after -> true, if before OR null (not exists) means -> false “used_when”需要更新为“using”,如果之后 -> true,如果之前 OR null(不存在)意味着 -> false

so it will look like:所以它看起来像:

[
    { "tax": true, "tax_percent": 20, "using": true },
    { "tax": false, "tax_percent": 20, "using": false },
    { "tax": false, "tax_percent": 20, "using": false }
]

The values are optional so not all entries will have it, also this is single row in database column so this data in column needs to be updated for each row.这些值是可选的,因此并非所有条目都有它,这也是数据库列中的单行,因此需要为每一行更新列中的数据。

step-by-step demo:db<>fiddle 分步演示:db<>fiddle

UPDATE t                                                                   -- 5
SET mydata = s.new_data
FROM (
    SELECT
        id,
        json_agg((using_updated - 'used_when')::json) as new_data          -- 4
    FROM t,
        json_array_elements(t.mydata) as elements,                         -- 1
        jsonb_set(elements::jsonb, '{tax}',                                -- 2
            CASE
                WHEN elements ->> 'tax' = 'yes' THEN 'true'::jsonb
                ELSE 'false'::jsonb
            END
        ) as tax_updated,
        jsonb_set(tax_updated::jsonb, '{using}',                           -- 3
            CASE
                WHEN tax_updated ->> 'used_when' = 'true' THEN 'true'::jsonb
                ELSE 'false'::jsonb
            END
        ) as using_updated
    GROUP BY id
) s
WHERE s.id = t.id;
  1. Extract all array elements into one element per record 2/3.将所有数组元素提取到每个记录 2/3 的一个元素中。 Now you can use jsonb_set() to insert new or update existing attributs within the array elements.现在您可以使用jsonb_set()在数组元素中插入新的或更新现有的属性。 The CASE clause does the condition check CASE子句进行条件检查
  2. Eliminate the remaining used_when elements.消除剩余的used_when元素。 Afterwards you can reaggregate the updated elements with json_agg之后,您可以使用 json_agg 重新聚合更新的元素
  3. Do the UPDATEUPDATE

If your data is type json, you have to do the casts to jsonb since, there is no json_set() .如果您的数据类型为 json,则必须对 jsonb 进行强制转换,因为没有json_set() If not, you can ignore the casts, of course.如果没有,你当然可以忽略演员表。

However, as @a_horse_with_no_name correctly mentioned: You should think about not storing these data as pure JSON but extract them into a normalized relative database table structure, which make things much easier and more performant.但是,正如@a_horse_with_no_name 正确提到的那样:您应该考虑不将这些数据存储为纯 JSON,而是将它们提取到规范化的相对数据库表结构中,这会使事情变得更容易和更高效。

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

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