更新postgres json中数组中的每个值

时间:2017-04-20 09:20:15

标签: json postgresql jsonb postgresql-9.5 postgresql-json

在我的postgres数据库中,我的json看起来与此类似:

{
    "myArray": [
        {
            "myValue": 1
        },
        {
            "myValue": 2
        },
        {
            "myValue": 3
        }
    ]
}

现在我想将myValue重命名为otherValue。我无法确定阵列的长度!我希望使用set_jsonb之类的通配符作为数组索引,但似乎不支持。那么最好的解决方案是什么?

2 个答案:

答案 0 :(得分:1)

您必须分解整个jsonb对象,修改单个元素并重新构建对象。

自定义功能会很有用:

create or replace function jsonb_change_keys_in_array(arr jsonb, old_key text, new_key text)
returns jsonb language sql as $$
    select jsonb_agg(case 
        when value->old_key is null then value
        else value- old_key || jsonb_build_object(new_key, value->old_key) 
        end)
    from jsonb_array_elements(arr)
$$;

使用:

with my_table (id, data) as (
values(1, 
'{
    "myArray": [
        {
            "myValue": 1
        },
        {
            "myValue": 2
        },
        {
            "myValue": 3
        }
    ]
}'::jsonb)
)

select 
    id, 
    jsonb_build_object(
        'myArray',
        jsonb_change_keys_in_array(data->'myArray', 'myValue', 'otherValue')
        )
from my_table;

 id |                           jsonb_build_object                           
----+------------------------------------------------------------------------
  1 | {"myArray": [{"otherValue": 1}, {"otherValue": 2}, {"otherValue": 3}]}
(1 row)

答案 1 :(得分:0)

使用json函数绝对是最优雅的,但你可以使用字符替换。将json(b)转换为文本,执行替换,然后将其更改回json(b)。在这个例子中,我包括了引号和冒号,以帮助文本替换目标json键而不会与值冲突。

CREATE TABLE mytable ( id INT, data JSONB );

INSERT INTO mytable VALUES (1, '{"myArray": [{"myValue": 1},{"myValue": 2},{"myValue": 3}]}');
INSERT INTO mytable VALUES (2, '{"myArray": [{"myValue": 4},{"myValue": 5},{"myValue": 6}]}');

SELECT * FROM mytable;

UPDATE mytable
SET data = REPLACE(data :: TEXT, '"myValue":', '"otherValue":') :: JSONB;

SELECT * FROM mytable;

http://sqlfiddle.com/#!17/1c28a/9/4