Поскольку массивы не имеют прямого доступа к элементам простым способом, мы можем попытаться подойти к этому по-другому, отключив вложенность -> фильтруя элементы -> объединяя элементы вместе. Я сформулировал пример кода с упорядоченными комментариями, чтобы помочь.
CREATE TABLE new_country AS
-- 4. Return a new array (for immutability) that contains the new desired set of colors
SELECT id, name, jsonb_set(extra_info, '{flag_colours}', new_colors, FALSE)
FROM country
-- 3. Use Lateral join to apply this to every row
LEFT JOIN LATERAL (
-- 1. First unnest the desired elements from the Json array as text (to enable filtering)
WITH prep AS (SELECT jsonb_array_elements_text(extra_info -> 'flag_colours') colors FROM country)
SELECT jsonb_agg(colors) new_colors -- 2. Form a new jsonb array after filtering
FROM prep
WHERE colors <> 'red') lat ON TRUE;
Если вы хотите обновить только затронутый столбец без воссоздания основной таблицы, вы можете:
UPDATE country
SET extra_info=new_extra_info
FROM new_country
WHERE country.id = new_country.id;
Я разбил его на два запроса, чтобы улучшить читаемость; однако вы также можете использовать подзапрос вместо создания новой таблицы (new_country).
С подзапросом он должен выглядеть так:
UPDATE country
SET extra_info=new_extra_info
FROM (SELECT id, name, jsonb_set(extra_info, '{flag_colours}', new_colors, FALSE) new_extra_info
FROM country
-- 3. Use Lateral join to scale this across tables
LEFT JOIN LATERAL (
-- 1. First unnest the desired elements from the Json array as text (to enable filtering)
WITH prep AS (SELECT jsonb_array_elements_text(extra_info -> 'flag_colours') colors FROM country)
SELECT jsonb_agg(colors) new_colors -- 2. Form a new jsonb array after filtering
FROM prep
WHERE colors <> 'red') lat ON TRUE) new_country
WHERE country.id = new_country.id;
Кроме того, вы можете фильтровать строки с помощью (Как из PostgreSQL 9,4):
SELECT *
FROM country
WHERE (extra_info -> 'flag_colours') ? 'red'