1

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:

[    { "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

"used_when" needs to be updated to "using" and if after -> true, if before OR null (not exists) means -> 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.

askedJan 21, 2021 at 14:47
trinny's user avatar
1
  • 1
    This would be so much easier with a properly normalized modelCommentedJan 21, 2021 at 14:51

1 Answer1

1

step-by-step demo:db<>fiddle

UPDATE t                                                                   -- 5SET mydata = s.new_dataFROM (    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) sWHERE s.id = t.id;
  1. Extract all array elements into one element per record2/3. Now you can usejsonb_set() to insert new or update existing attributs within the array elements. TheCASE clause does the condition check
  2. Eliminate the remainingused_when elements. Afterwards you can reaggregate the updated elements with json_agg
  3. Do theUPDATE

If your data is type json, you have to do the casts to jsonb since, there is nojson_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.

answeredJan 21, 2021 at 15:07
S-Man's user avatar
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

Sign up orlog in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

By clicking “Post Your Answer”, you agree to ourterms of service and acknowledge you have read ourprivacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.