简体   繁体   English

Postgres - 更新 json 列中的数组元素

[英]Postgres - updating an array element in a json column

I have a json column in a postgres table.我在 postgres 表中有一个 json 列。 The column contains the following json data:该列包含以下 json 数据:

{
    "data": {
        "id": "1234",
        "sites": [
            {
                "site": {
                    "code": "1",
                    "display": "Site1"
                }
            },
            {
                "site": {
                    "code": "2",
                    "display": "Site2"
                },
                "externalSite": true
            },
            {
                "site": {
                    "code": "3",
                    "display": "Site3"
                }
            }
        ]
    }
}

I need to create an update query that adds another attribute ('newAttribute' in the sample below) to all array items that have '"externalSite": true', so, after running the update query the second array element will be:我需要创建一个更新查询,将另一个属性(下面示例中的“newAttribute”)添加到所有具有“externalSite”:true”的数组项中,因此,在运行更新查询后,第二个数组元素将是:

{
    "site": {
        "code": "2",
        "display": "Site2"
    },
    "externalSite": true,
    "newAttribute": true
}

The following query returns the array elements that need to be updated: select * from myTable, jsonb_array_elements(data -> 'sites') sites where sites ->'externalSite' = 'true'以下查询返回需要更新的数组元素: select * from myTable, jsonb_array_elements(data -> 'sites') sites where sites ->'externalSite' = 'true'

What is the syntax of the update query?更新查询的语法是什么?

Thanks Kobi谢谢科比

Assuming your table is called test and your column is called data , you can update it like so:假设您的表名为test并且您的列名为data ,您可以像这样更新它:

UPDATE test SET data = 
  (select jsonb_set(data::jsonb, '{"data","sites"}', sites)
  FROM test
  CROSS JOIN LATERAL (
      SELECT jsonb_agg(CASE WHEN site ? 'externalSite' THEN site || '{"newAttribute":"true"}'::jsonb
                  ELSE site
             END) AS sites
      FROM jsonb_array_elements( (data#>'{"data","sites"}')::jsonb ) as ja(site)
  ) as sub
);

Note that I cast the data to jsonb data as there are more functions and operators available for manipulating jsonb than plain json.请注意,我将数据转换为 jsonb 数据,因为与普通 json 相比,有更多的函数和运算符可用于操作 jsonb。

You can run the SELECT statement alone to see what it is doing, but the basic idea is to re-create the sites object by expanding it with jsonb_array_elements and adding the newAttribute attribute if externalSite exists.您可以单独运行 SELECT 语句以查看它在做什么,但基本思想是通过使用 jsonb_array_elements 扩展它并添加newAttribute属性(如果externalSite存在)来重新创建sites对象。

This array is then aggregated with jsonb_agg and, finally, in the outer select, the sites object is replaced entirely with this newly computed version.这个数组然后与 jsonb_agg 聚合,最后,在外部选择中, sites对象被这个新计算的版本完全替换。

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

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