Вставка нового элемента в json объект вложенных массивов в JSONB_SET - PullRequest
1 голос
/ 09 февраля 2020

У меня есть таблица (log_table), и в этой таблице есть вложенный массив json поле (деятельность). Используя это поле действий, я хочу вставить новое поле во вложенный массив.

log_table:

- id:long
- activities:json
- date:timestamp

пример поля действий:

[ 
   { 
      "actionType":"NOTIFICATION",
      "items":null
   },
   { 
      "actionType":"MUTATION",
      "items":[ 
         { 
            "id":387015007,
            "name":"epic",
            "value":{ 
               "currency":"USD",
               "amount":1.76
            }
         },
         { 
            "id":386521039,
            "name":"test",
            "value":{ 
               "currency":"USD",
               "amount":1.76
            }
         }
      ]
   }
]

Как запрос, я попробовал:

update 
table_log m 
set activities = 
jsonb_set(
   m.activities::jsonb, 
   array['activities',(pos1-1)::text,'items',(pos-1)::text,'newId'],
   ((obj->>'id'))::jsonb 
)::json
from table_log l
cross join jsonb_array_elements(l.activities::jsonb) with ordinality arr1(elems, pos1)
cross join jsonb_array_elements(case elems->'items' when 'null' then '[null]' else elems->'items' end)  with ordinality arr(obj, pos)
where (obj->>'id')::int = 387015007 and l.id = m.id;

В этом запросе я получил ошибку, подобную приведенной ниже:

ERROR:  path element at position 1 is not an integer: "activities"

Ожидаемый результат:

[ 
   { 
      "actionType":"NOTIFICATION",
      "items":null
   },
   { 
      "actionType":"MUTATION",
      "items":[ 
         { 
            "id":387015007,
            "newId":387015007,
            "name":"epic",
            "value":{ 
               "currency":"USD",
               "amount":1.76
            }
         },
         { 
            "id":386521039,
            "name":"test",
            "value":{ 
               "currency":"USD",
               "amount":1.76
            }
         }
      ]
   }
]

Есть ли какие-либо предложения?

1 Ответ

1 голос
/ 09 февраля 2020

Решено, как показано ниже:

update 
table_log m 
set activities = 
jsonb_set(
   m.activities::jsonb, 
   array[(pos1-1)::text,'items',(pos-1)::text,'newId'],
   ((obj->>'id'))::jsonb 
)::json
from table_log l
cross join jsonb_array_elements(l.activities::jsonb) with ordinality arr1(elems, pos1)
cross join jsonb_array_elements(case elems->'items' when 'null' then '[null]' else elems->'items' end)  with ordinality arr(obj, pos)
where (obj->>'id')::int = 387015007 and l.id = m.id;

Итак, проблема была:

array['activities',...] -> «деятельность» здесь избыточна.

...