JSONB в PostgresSQL 11.6 - обновить все вхождения элемента для указанного условия c - PullRequest
0 голосов
/ 07 февраля 2020

Я изучаю JSONB в PostgreSQL версии - 11.6. У меня есть требование, где я хочу обновить все вхождения, где появляется определенное условие.

Рассмотрим приведенный ниже пример:

CREATE TABLE parts(id bigint NOT NULL GENERATED ALWAYS AS IDENTITY, parts_data jsonb);

insert into parts (parts_data) values
( '{
    "Parts": {
        "CreatedBy": "M95183638_95183638",
        "PartsId": "00cb9cd6-37c5-41ca-b61c-a0f275d5d913",
        "PartData": {
            "Vendors": [
                {
                    "VendorId": "1",
                    "Preferences": [
                        {
                            "CategoryId": 5582,
                            "SubcategoryId": 5583
                        },
                        {
                            "CategoryId": 5584,
                            "SubcategoryId": 5700
                        },
                        {
                            "CategoryId": 5582,
                            "SubcategoryId": 5697
                        },                      
                        {
                            "CategoryId": 5854,
                            "ClassCodes": [
                                {
                                    "ClassCode": 971011,
                                    "IsCertifiable": false
                                }
                            ]
                        }
                    ]
                }
            ]
        }
    }
}'::jsonb);

Я хочу обновить SubcategoryId для всех элементов, где CategoryId = 5582. Когда я запускаю приведенный ниже запрос, он обновит только 1 экземпляр categoryID.

with data as
(
select path
FROM   parts np
       ,  LATERAL ( select ARRAY['Parts', 'PartData','Vendors', (vndr.index - 1)::text, 'Preferences', (pref.index - 1)::text, 'SubcategoryId'] as path
                     FROM   jsonb_array_elements(parts_data #> '{Parts,PartData, Vendors}') WITH ORDINALITY vndr(opt, index) 
                          , jsonb_array_elements(vndr.opt->'Preferences') with ordinality as pref(opt, index)
                    WHERE pref.opt ->> 'CategoryId'= '5582'
                  ) a
WHERE parts_data->'Parts' ->> 'PartsId'='00cb9cd6-37c5-41ca-b61c-a0f275d5d913'
)        
update  parts np
   set parts_data = jsonb_set(np.parts_data, path, '44444'::jsonb, false)
  from data p1
 where np.parts_data->'Parts' ->> 'PartsId'='00cb9cd6-37c5-41ca-b61c-a0f275d5d913';

Чтобы обновить все экземпляры, я думал о циклическом прохождении всех вхождений и обновлении каждого экземпляра, но это не кажется чистым решением. Есть ли способ обновить все экземпляры, где CategoryId = '5582' в одном операторе UPDATE?

...