jsonb
в Postgres 9.4 или позже
Рассмотрим jsonb
тип данных в Postgres 9.4 - «b» для «двоичного». Помимо прочего, есть оператор равенства =
дляjsonb
. Большинство людей захотят переключиться.
Блог Depesz о JSONB.
json
Для =
типа данных не определен оператор json
, поскольку нет четко определенного метода для установления равенства для целых json
значений. Но смотри ниже.
Вы можете привести к text
и затем использовать =
оператор. Это коротко, но работает, только если ваше текстовое представление совпадает. По своей сути ненадежны, за исключением угловых случаев. Видеть:
Или вы можете unnest
массив и использовать ->>
оператор, чтобы .. get JSON object field as text
и сравнить отдельные поля.
Тестовый стол
2 строки: первая, как в вопросе, вторая с простыми значениями.
CREATE TABLE tbl (
tbl_id int PRIMARY KEY
, jar json[]
);
INSERT INTO t VALUES
(1, '{"{\"value\" : \"03334/254146\", \"typeId\" : \"ea4e7d7e-7b87-4628-ba50-f5\"}"
,"{\"value\" : \"03334/254147\", \"typeId\" : \"ea4e7d7e-7b87-4628-ba50-f6\"}"
,"{\"value\" : \"03334/254148\", \"typeId\" : \"ea4e7d7e-7b87-4628-ba50-f7\"}"}')
, (2, '{"{\"value\" : \"a\", \"typeId\" : \"x\"}"
,"{\"value\" : \"b\", \"typeId\" : \"y\"}"
,"{\"value\" : \"c\", \"typeId\" : \"z\"}"}');
демос
Демонстрация 1: вы можете использовать array_remove()
с text
представлениями (ненадежными).
SELECT tbl_id
, jar, array_length(jar, 1) AS jar_len
, jar::text[] AS t, array_length(jar::text[], 1) AS t_len
, array_remove(jar::text[], '{"value" : "03334/254147", "typeId" : "ea4e7d7e-7b87-4628-ba50-f6"}'::text) AS t_result
, array_remove(jar::text[], '{"value" : "03334/254147", "typeId" : "ea4e7d7e-7b87-4628-ba50-f6"}'::text)::json[] AS j_result
FROM tbl;
Демонстрация 2: раскрутить массив и проверить поля отдельных элементов.
SELECT tbl_id, array_agg(j) AS j_new
FROM tbl, unnest(jar) AS j -- LATERAL JOIN
WHERE j->>'value' <> '03334/254146'
AND j->>'typeId' <> 'ea4e7d7e-7b87-4628-ba50-6a5f6e63dbf5'
GROUP BY 1;
Демонстрация 3: альтернативный тест с типом строки.
SELECT tbl_id, array_agg(j) AS j_new
FROM tbl, unnest(jar) AS j -- LATERAL JOIN
WHERE (j->>'value', j->>'typeId') NOT IN (
('03334/254146', 'ea4e7d7e-7b87-4628-ba50-6a5f6e63dbf5')
,('a', 'x')
)
GROUP BY 1;
UPDATE
как просили
Наконец, вот как вы можете реализовать UPDATE
:
UPDATE tbl t
SET jar = j.jar
FROM tbl t1
CROSS JOIN LATERAL (
SELECT ARRAY(
SELECT j
FROM unnest(t1.jar) AS j -- LATERAL JOIN
WHERE j->>'value' <> 'a'
AND j->>'typeId' <> 'x'
) AS jar
) j
WHERE t1.tbl_id = 2 -- only relevant rows
AND t1.tbl_id = t.tbl_id;
дБ <> скрипка здесь
О неявном LATERAL JOIN
:
О несмешивающихся массивах:
Дизайн БД
Чтобы упростить ситуацию, рассмотрим нормализованную схему : отдельную таблицу для json
значений (вместо столбца массива), объединенную в отношении: 1 к основной таблице.