Удалить элемент из массива jsonb - PullRequest
0 голосов
/ 05 марта 2019

У меня есть следующий jsonb.Из страниц массива я хотел бы удалить элемент под названием «pageb».Решения, предложенные в подобных вопросах, не работают для меня.

'{
  "data": {
    "id": "a1aldjfg3f",
    "pages": [
      {
        "type": "pagea"
      },
      {
        "type": "pageb"
      }                                
    ],
    "activity": "test"
  }
}'

Мой сценарий сейчас выглядит следующим образом.Он не возвращает никакой ошибки, но элементы не будут удалены.

  UPDATE database
  SET reports = jsonb_set(reports, '{data,pages}', (reports->'data'->'pages') - ('{"type":"pageb"}'), true)
  WHERE reports->'data'->'pages'  @> '[{"type":"pageb"}]';

Ответы [ 2 ]

1 голос
/ 06 марта 2019

Оператор - не может быть применен здесь, потому что правый операнд является строкой, определяющей ключ, согласно документации:

Удалить пару ключ / значение или строковый элемент из левого операнда. Пары ключ / значение сопоставляются на основе их значения ключа.

Удаление объекта json из массива json можно выполнить, распаковав массив и найдя индекс объекта. Запрос с использованием этого метода может быть слишком сложным, поэтому определение пользовательской функции очень удобно в этом случае.

create or replace function jsonb_remove_array_element(arr jsonb, element jsonb)
returns jsonb language sql immutable as $$
    select arr- (
        select ordinality- 1
        from jsonb_array_elements(arr) with ordinality
        where value = element)::int
$$;

И обновление:

update my_table
set reports = 
    jsonb_set(
        reports, 
        '{data,pages}', 
        jsonb_remove_array_element(reports->'data'->'pages', '{"type":"pageb"}')
        )
where reports->'data'->'pages'  @> '[{"type":"pageb"}]';

Рабочий пример в rextester.

0 голосов
/ 06 марта 2019

Ниже приводится комбинация ответа , предоставленного для надежного удаления элемента внутри массива, и способности PostgreSQL использовать изменяющие данные WITH операторы , но для этого требуется столбец идентификаторов (id в моей таблице test) для работы из-за необходимой корреляции:

WITH new_reports AS (
    SELECT
        id,
        reports #- array['data','pages',(position - 1)::text] AS new_value
    FROM
        test,
        jsonb_array_elements(reports->'data'->'pages') WITH ORDINALITY arr(item, position)
    WHERE
        test.reports->'data'->'pages' @> '[{"type":"pageb"}]'
        AND
        item->>'type' = 'pageb'
    )
UPDATE test SET reports = new_reports.new_value FROM new_reports WHERE test.id = new_reports.id;

Данные испытаний, которые я использовал:

SELECT reports FROM test;
                                               reports                                               
-----------------------------------------------------------------------------------------------------
 {"data": {"id": "a1aldjfg3f", "pages": [{"type": "pagea"}, {"type": "pagec"}], "activity": "test"}}
 {"data": {"id": "a1aldjfg3f", "pages": [{"type": "pagea"}, {"type": "pageb"}], "activity": "test"}}
 {"data": {"id": "a1aldjfg3f", "pages": [{"type": "pageb"}, {"type": "pagec"}], "activity": "test"}}
(3 rows)

... и после выполнения запроса:

SELECT reports FROM test;
                                               reports                                               
-----------------------------------------------------------------------------------------------------
 {"data": {"id": "a1aldjfg3f", "pages": [{"type": "pagea"}, {"type": "pagec"}], "activity": "test"}}
 {"data": {"id": "a1aldjfg3f", "pages": [{"type": "pagea"}], "activity": "test"}}
 {"data": {"id": "a1aldjfg3f", "pages": [{"type": "pagec"}], "activity": "test"}}
(3 rows)

Я надеюсь, что это работает для вас.

...