Добавить / обновить объекты и элементы в массивах NESTED JSONB с PostgreSQL - PullRequest
0 голосов
/ 22 февраля 2020

Json запрос:

INSERT INTO test.demotbl (data)
VALUES ('{
    "x1": "Americas",
    "x2": "West",
    "x3": [{
        "x_id": "sam"
    }],
    "x4": {
        "a1": true,
        "a2": false,
        "a3": [
            "xx",
            "xx"
        ],
        "a4": [
            "Josh"
        ],
        "y1": [{
                "id": "RW",
                "z2": true,
                "z3": "USER"

            },
            {
                "id": "RO",
                "z2": false,
                "z3": "SELECT"

            }
        ]
    }
}'::jsonb)

Я хочу обновить поле z4 на основе идентификатора "id": "RO".

У меня был подобный случай использования здесь, когда мне было нужно чтобы обновить поле z4, используемое ниже запрос:

with zd as (select ('{x4,y1,'||index-1||',z4}')::text[] as path
            from table1
            ,jsonb_array_elements((field1->>'x4')::jsonb->'y1') 
            with ordinality arr(x,index)
            where x->>'id'='RO'
        )
update table1
set field1=jsonb_set(field1,zd.path,to_jsonb('[ { "name": "john" } ]'::jsonb),false)
from zd

Но теперь в текущем json поле X4 не существует, и мне нужно добавить "z4": [{"name": "john" } вместо простого обновления поля

Ожидаемый результат:

{
    "x1": "Americas",
    "x2": "West",
    "x3": [{
        "x_id": "sam"
    }],
    "x4": {
        "a1": true,
        "a2": false,
        "a3": [
            "xx",
            "xx"
        ],
        "a4": [
            "Josh"
        ],
        "y1": [{
                "id": "RW",
                "z2": true,
                "z3": "USER"

            },
            {
                "id": "RO",
                "z2": false,
                "z3": "SELECT",
                "z4": [{
                    "name": "john"
                }]
            }
        ]
    }
}

Может ли вышеуказанный запрос быть изменен или предложить новый запрос, который будет работать как для добавления (если поданного z4 не существует), так и для обновить поданный z4 пример "z4": [{"name": "john"}, {"name": "Steve"}], если поданный z4 присутствует.

1 Ответ

0 голосов
/ 22 февраля 2020

Если вы хотите добавить z4, вам нужно только изменить последний аргумент в функции jsonb_set на «true» вместо «false». Это дает указание функции создать поле, если оно не существует. Вам нужно изменить to_jsonb (...) на '....' :: jsonb для разбора массива.
Это должно работать:

with zd as (select ('{x4,y1,'||index-1||',z4}')::text[] as path
            from table1
            ,jsonb_array_elements((field1->>'x4')::jsonb->'y1') 
            with ordinality arr(x,index)
            where x->>'id'='RO'
        )
update table1
set field1=jsonb_set(field1,zd.path,'[{ "name": "john" },{ "name": "Steve" }]'::jsonb,true)
from zd

Надеюсь, я правильно вставил и изменено здесь: -)
С уважением,
Bjarni

...