2

Very similar to this post, but I struggle to adapt from their solution..

My table : public.challenge, column lines JSONB

My initial JSON in lines :

[
  {
    "line": 1,
    "blocs": [
      {
        "size": 100,
        "name": "abc"
      },
      {
        "size": 100,
        "name": "def"
      },
      {
        "size": 100,
        "name": "ghi"
      }
    ]
  },
  {
    "line": 2,
    "blocs": [
      {
        "size": 100,
        "name": "xyz"
      }
    ]
  }
]

Desired update :

[
  {
    "line": 1,
    "blocs": [
      {
        "size": 100,
        "name": "abc",
        "type": "regular"
      },
      {
        "size": 100,
        "name": "def",
        "type": "regular"
      },
      {
        "size": 100,
        "name": "ghi",
        "type": "regular"
      }
    ]
  },
  {
    "line": 2,
    "blocs": [
      {
        "size": 100,
        "name": "xyz",
        "type": "regular"
      }
    ]
  }
]

So basically I need to add the type key+value in every object of blocs, for each element of the root array.

My unsuccessful attempt looks like this :

UPDATE public.challenge SET lines = jsonb_set(lines, '{}', (

    SELECT jsonb_set(line, '{blocs}', (
        SELECT jsonb_agg( bloc || '{"type":"regular"}' )
        FROM jsonb_array_elements(line->'{blocs}') bloc
    ))

    FROM jsonb_array_elements(lines) line
))
;

(currently it sets the whole column as null, maybe due to jsonb_set(lines, '{}' while my json begins as an array ?)

Thanks!

1 Answer 1

2

Use jsonb_array_elements to unnest all the array elements and then add the required json and use jsonb_agg to aggregate it again:

with cte as
 (select id,
         jsonb_agg(jsonb_set(val1,
                             '{blocs}',
                             (select jsonb_agg(arr2 || '{"type": "regular"}')
                                from jsonb_array_elements(arr1.val1 - >
                                                          'blocs') arr2)))
    from challenge, 
         jsonb_array_elements(lines) arr1(val1)
   group by 1) 
update challenge 
   set lines = (cte.jsonb_agg) 
  from cte 
 where challenge.id = cte.id

DEMO

Sign up to request clarification or add additional context in comments.

1 Comment

Great thanks! By any chance, I'd like the value to be arr2->'oldType' (instead of always "regular"), how would you concatenate this in the jsonb_agg function ?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy 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.