Check If A Postgres JSON Array Contains A String


Answer :

As of PostgreSQL 9.4, you can use the ? operator:

select info->>'name' from rabbits where (info->'food')::jsonb ? 'carrots'; 

You can even index the ? query on the "food" key if you switch to the jsonb type instead:

alter table rabbits alter info type jsonb using info::jsonb; create index on rabbits using gin ((info->'food')); select info->>'name' from rabbits where info->'food' ? 'carrots'; 

Of course, you probably don't have time for that as a full-time rabbit keeper.

Update: Here's a demonstration of the performance improvements on a table of 1,000,000 rabbits where each rabbit likes two foods and 10% of them like carrots:

d=# -- Postgres 9.3 solution d=# explain analyze select info->>'name' from rabbits where exists ( d(# select 1 from json_array_elements(info->'food') as food d(#   where food::text = '"carrots"' d(# );  Execution time: 3084.927 ms  d=# -- Postgres 9.4+ solution d=# explain analyze select info->'name' from rabbits where (info->'food')::jsonb ? 'carrots';  Execution time: 1255.501 ms  d=# alter table rabbits alter info type jsonb using info::jsonb; d=# explain analyze select info->'name' from rabbits where info->'food' ? 'carrots';  Execution time: 465.919 ms  d=# create index on rabbits using gin ((info->'food')); d=# explain analyze select info->'name' from rabbits where info->'food' ? 'carrots';  Execution time: 256.478 ms 

You could use @> operator to do this something like

SELECT info->>'name' FROM rabbits WHERE info->'food' @> '"carrots"'; 

Not smarter but simpler:

select info->>'name' from rabbits WHERE info->>'food' LIKE '%"carrots"%'; 

Comments

Popular posts from this blog

Are Regular VACUUM ANALYZE Still Recommended Under 9.1?

Can Feynman Diagrams Be Used To Represent Any Perturbation Theory?