简体   繁体   中英

How to update multiple values in JSONB array Postgresql array object

I have a JSONB array below

[
  {"name":"test","age":"21","phone":"6589","town":"54"},
  {"name":"test12","age":"67","phone":"6546","town":"54"}
]

Now I want to update town , phone , age if name is test . How to update multiple values in JSONB array?

Below query will give you results which contains test word in them. After you find these you can update any values in other columns.

Working Demo

 CREATE TABLE TEST2 (
    INFO JSON NOT NULL
);

INSERT INTO TEST2 (info)
VALUES('[
  {"name":"test","age":"21","phone":"6589","town":"54"},
  {"name":"test12","age":"67","phone":"6546","town":"54"},
  {"name":"dest147","age":"67","phone":"6546","town":"54"}
]');

SELECT *
FROM TEST2,
json_array_elements(info) elem
WHERE elem ->> 'name' like '%test%';

You can update them dynamically by indexing each individual element:

For age :

WITH s AS
(
 SELECT ('{'||idx-1||',age}')::text[] AS path
   FROM tab 
  CROSS JOIN jsonb_array_elements(jsdata) 
   WITH ORDINALITY arr(j,idx)
  WHERE j->>'name'='test' 
)
UPDATE tab
   SET jsdata = jsonb_set(jsdata,s.path,'"15"',false)
  FROM s

For town :

WITH s AS
(
 SELECT ('{'||idx-1||',town}')::text[] AS path
   FROM tab 
  CROSS JOIN jsonb_array_elements(jsdata) 
   WITH ORDINALITY arr(j,idx)
  WHERE j->>'name'='test' 
)
UPDATE tab
   SET jsdata = jsonb_set(jsdata,s.path,'"55"',false)
  FROM s

For phone :

WITH s AS
(
 SELECT ('{'||idx-1||',phone}')::text[] AS path
   FROM tab 
  CROSS JOIN jsonb_array_elements(jsdata) 
   WITH ORDINALITY arr(j,idx)
  WHERE j->>'name'='test' 
)
UPDATE tab
   SET jsdata = jsonb_set(jsdata,s.path,'"1111"',false)
  FROM s

Demo

Or directly at a time :

WITH s AS
(
 SELECT ('{'||idx-1||',phone}')::text[] AS path_phone,
        ('{'||idx-1||',town}')::text[] AS path_town,
        ('{'||idx-1||',age}')::text[] AS path_age
   FROM tab 
  CROSS JOIN jsonb_array_elements(jsdata) 
   WITH ORDINALITY arr(j,idx)
  WHERE j->>'name'='test' 
)
UPDATE tab
   SET jsdata = jsonb_set(jsonb_set(jsonb_set(jsdata,
                                              s.path_phone,
                                              '"1111"',
                                              false),
                                    path_town,
                                    '"55"',
                                    false),
                          s.path_age,
                          '"20"',
                          false)
      FROM s

Demo

This query is longer, but it should clarify expanding the original column to make the replacements:

with injson as (
  select '[
  {"name":"test","age":"21","phone":"6589","town":"54"},
  {"name":"test12","age":"67","phone":"6546","town":"54"}
]'::jsonb as jarray
), substitution as (
  select '{"name": "test", "age": "22", "phone": "6590", "town": "55"}'::jsonb as jnew
), expand as (
  select jsonb_array_elements(jarray) as jold
    from injson
), cond_update as (
  select coalesce(s.jnew, e.jold) as element
    from expand e
         left join substitution s
                on s.jnew->>'name' = e.jold->>'name'
)
select jsonb_agg(element) as result
  from cond_update;
                                                             result                                                             
--------------------------------------------------------------------------------------------------------------------------------
 [{"age": "22", "name": "test", "town": "55", "phone": "6590"}, {"age": "67", "name": "test12", "town": "54", "phone": "6546"}]
(1 row)

Based on the description of your table, it should look something like this:

with substitution as (
  select '{"name": "test", "age": "22", "phone": "6590", "town": "55"}'::jsonb as jnew
), expand as (
  select id, jsonb_array_elements("caloriesConsumption") as jold
    from "calorieTracker"
   where id = 1
), cond_update as (
  select id, coalesce(s.jnew, e.jold) as element
    from expand e
         left join substitution s
                on s.jnew->>'name' = e.jold->>'name'
)
update "calorieTracker" 
   set "caloriesConsumption" = cu.element
  from cond_update
 where cond_update.id = "calorieTracker".id;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM