There is currently no =
operator defined for the data type json
, because there is no well defined method to establish equality of the whole json
values. But see below.
You could cast to text
and use the =
operator then. This is short, but only works if your text representation matches and is unreliable.
Or you can unnest
the array and use the ->>
operator to .. get JSON object field as text
and compare individual fields.
I cannot provide an SQL Fiddle, for some methods for arrays of json
are "not yet implemented" in JDBC. Try this at home (pg 9.3+):
Test table
2 rows: first one like in the question, second one with simple values.
CREATE TABLE t (
t_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\"}"}');
Demos
Demo 1: you could use array_remove()
with text
representations (unreliable).
SELECT t_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 t;
Demo 2: unnest the array and test fields of individual elements.
SELECT t_id, array_agg(j) AS j_new
FROM t
, unnest(jar) AS j -- LATERAL JOIN
WHERE j->>'value' <> '03334/254146'
AND j->>'typeId' <> 'ea4e7d7e-7b87-4628-ba50-6a5f6e63dbf5'
GROUP BY 1;
Demo 3: alternative test with row type.
SELECT t_id, array_agg(j) AS j_new
FROM t
, 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 as requested
Finally, this is how you could implement your UPDATE:
UPDATE t
SET jar = sub.jar
FROM (
SELECT t_id, array_agg(j) AS jar
FROM (SELECT t_id, jar FROM t WHERE t_id = 2) t -- reduce to relevant rows
, unnest(jar) AS j -- LATERAL JOIN
WHERE j->>'value' <> 'a'
AND j->>'typeId' <> 'x'
GROUP BY 1
) sub
WHERE t.t_id = sub.t_id;
More about the implicit LATERAL JOIN
:
And about unnesting arrays:
DB design
To simplify your situation consider an normalized schema: a separate table for the json
values (instead of the array column), joined in a n:1 relationship to the main table.
jsonb
in Postgres 9.4
You will be interested in the jsonb
data type in Postgres 9.4. 'b' is for 'binary'. Among other things, there is an equality operator =
for jsonb
. Most people will want switch to jsonb
.
Depesz blog about jsonb.