Как удалить объект JSON из массива JSON в Postgres?

#sql #postgresql #jsonb

Вопрос:

Я новичок в Postgres. Я хочу удалить объект JSON из массива JSON.

У меня есть таблица, в которой я использую столбец jsonb, в котором я сохраняю массив JSON, как показано ниже.

 [
  {
    "id": "c75e7a-001e-4d64-9613-62f666d42103",
    "name": "Product1"
  },
  {
    "id": "c75e7a-001e-4d64-9613-62f666d42103",
    "name": null
  },
  {
    "id": "c75e7a-001e-4d64-9613-62f666d42103",
    "name": "Product2"
  },
  {
    "id": "c75e7a-001e-4d64-9613-62f666d42103",
    "name": null
  }
]
 

Я хочу удалить объекты JSON из массива, который содержит нулевое значение в ключе name.

после удаления ответ должен быть таким

 [
  {
    "id": "c75e7a-001e-4d64-9613-62f666d42103",
    "name": "Product1"
  },
  {
    "id": "c75e7a-001e-4d64-9613-62f666d42103",
    "name": "Product2"
  }
]
 

кто-нибудь, пожалуйста, помогите мне написать SQL-запрос,

Я знаю, как получить все записи из таблицы, которая содержит нулевое значение.

 SELECT * 
  FROM table_name 
 WHERE jsonb_col_name @>CAST('[{"name": null}]' AS JSONB);
 

Но я не знаю, как сделать запрос на удаление, пожалуйста, помогите мне с этим.
Как я могу это сделать с помощью запроса?

Ответ №1:

Отмените массив с jsonb_array_elements помощью, исключите null значения с помощью a FILTER и снова объедините их, например

 SELECT 
  jsonb_agg(j) FILTER (WHERE j->>'name' IS NOT NULL)
FROM table_name t, jsonb_array_elements(jsonb_col) j 
GROUP BY t.jsonb_col;
 

ДЕМОНСТРАЦИЯ: db<>fiddle

Ответ №2:

Вы можете отфильтровать j.value ->> 'name' IS NOT NULL после разделения массива на подобъекты с помощью JSONB_ARRAY_ELEMENTS , а затем применить JSONB_AGG , чтобы преобразовать его обратно в массив, например

 SELECT JSONB_PRETTY(
                    JSONB_AGG(j)
                   )
  FROM t, 
       JSONB_ARRAY_ELEMENTS(json_data) AS j
 WHERE j.value ->> 'name' IS NOT NULL
 GROUP BY json_data
 

Если необходимо обновить существующие данные, вы можете рассмотреть возможность использования

 WITH tt AS
(
SELECT JSONB_AGG(j) AS new_val,
       json_data            
  FROM t, 
       JSONB_ARRAY_ELEMENTS(json_data) AS j
 WHERE j.value ->> 'name' IS NOT NULL
 GROUP BY json_data
)
UPDATE t
   SET json_data = new_val::JSONB
  FROM tt
 WHERE t.json_data = tt.json_data
 

Demo

Ответ №3:

Вы можете использовать json_array_elements :

 select json_agg(i.value) from json_array_elements('[{"id": "c75e7a-001e-4d64-9613-62f666d42103", "name": "Product1"}, {"id": "c75e7a-001e-4d64-9613-62f666d42103", "name": null}, {"id": "c75e7a-001e-4d64-9613-62f666d42103", "name": "Product2"}, {"id": "c75e7a-001e-4d64-9613-62f666d42103", "name": null}]') v 
where (v.value -> 'name')::text != 'null'
 

Вывод:

 [{"id": "c75e7a-001e-4d64-9613-62f666d42103", "name": "Product1"}, {"id": "c75e7a-001e-4d64-9613-62f666d42103", "name": "Product2"}]