I need to perform two update operations:
- update change data from string to bool in first case
- 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.
- 1This would be so much easier with a properly normalized modeluser330315– user3303152021-01-21 14:51:36 +00:00CommentedJan 21, 2021 at 14:51
1 Answer1
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;- Extract all array elements into one element per record2/3. Now you can use
jsonb_set()to insert new or update existing attributs within the array elements. TheCASEclause does the condition check - Eliminate the remaining
used_whenelements. Afterwards you can reaggregate the updated elements with json_agg - Do the
UPDATE
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.
Comments
Explore related questions
See similar questions with these tags.
