PostgreSQL JSON query modify an array

Viewed 33

I have a some json configuration in the table something like below

create table X (name varchar, config json);

insert into X (name, config) values (
  'name1',
  '{"method":"XYZ","frequent":["MONTHLY","WEEKLY"]}'  
);

insert into X (name, config) values (
  'name2',
  '{"method":"ABC","frequent":["WEEKLY", "DAILY"]}'  
);

Basically this frequent property in json column can contain any number of elements as this is an array.

Now I want to modify all the records in a table where "frequent":["MONTHLY", "WEEKLY"] to "frequency":["P1M","P1W"] and so on..

So output should be something like that

'name1','{"method":"XYZ","frequency":["P1M","P1W"]}'
'name2','{"method":"ABC","frequency":["P1W","P1D"]}'  

Should I go with CASE WHEN and THEN approach or is there any better way to do that?

version : 9.5+

1 Answers

If you have to use more complex rules than just taking the first character of the original frequency word (e.g. 1 if it's less than a month, 3 if it's a quarter), you have to use CASE WHEN .... The whole update query will look like this:

WITH modified_frequencies AS (
    SELECT 
        name,
        config::jsonb->'method'::text AS method,
        CASE
            WHEN frequency_word = 'MONTHLY' THEN 'P1M'
            WHEN frequency_word = 'WEEKLY' THEN 'P1W'
            WHEN frequency_word = 'DAILY' THEN 'P1D'
            WHEN frequency_word = 'QUARTERLY' THEN 'P3M'
        END AS modified_frequency_word
    FROM test.X, 
         json_array_elements_text((config::jsonb->'frequent')::json) AS frequency_word
),
    modified_configs AS (
        SELECT
            name,
            json_build_object(
                'method', method,
                'frequent', array_agg(modified_frequency_word)
            ) AS modified_config
        FROM modified_frequencies
        GROUP BY name, method
)
UPDATE test.X x
SET config = modified_config
FROM modified_configs
WHERE x.name = modified_configs.name

Basically, you have to first unnest the JSON array, so that you can work on the individual elements in it, then put back the whole JSON structure together, which then you can use in the update statement.

Related