Postgresql 和 jsonb - 将 key/value 插入多级数组

Postgresql and jsonb - inserting a key/value into a multi-level array

非常相似,但我很难适应他们的解决方案..

我的table:public.challenge,列lines JSONB

我在 lines 中的初始 JSON :

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

需要的更新:

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

所以基本上我需要在 blocs 的每个对象中为根数组的每个元素添加 type 键+值。

我失败的尝试是这样的:

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
))
;

(目前它将整个列设置为空,可能是由于 jsonb_set(lines, '{}' 而我的 json 以数组开始?)

谢谢!

使用jsonb_array_elements取消所有数组元素的嵌套,然后添加所需的json并再次使用jsonb_agg聚合:

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