I have a jsonb[]
column in my table named jsonb_column
, which contains an array of JSONB objects. For example:
jsonb_column = '{"{\"title\":\"title1\"}"
,"{\"title\":\"title2\"}"}'
I'm attempting to extract the JSONB object where the title field is equal to 'title2'.
SELECT *
FROM tablename,
jsonb_array_elements(jsonb_column) AS job
WHERE job->>'title' = 'title2';
It doesn't return anything. How to do it properly?
A mix-up of jsonb[]
(containing jsonb
values that, in turn, contain a plain JSON object) with a JSON array stored as jsonb
.
jsonb[]
jsonb[]
is a Postgres array. To unnest, use unnest()
:
CREATE TABLE tbl (id int, js jsonb[]);
INSERT INTO tbl VALUES
(1, '{"{\"title\":\"title1\"}","{\"title\":\"title2\"}"}')
;
SELECT *
FROM tbl, unnest(js) AS job
WHERE job->>'title' = 'title2';
fiddle - dbfiddle currently swallows necessary backslashes in the display. I reported a bug.
Related:
jsonb
This is where you could use jsonb_array_elements()
like you tried:
CREATE TABLE tbl (id int, js jsonb);
INSERT INTO tbl VALUES
(1, '[{"title":"title1"},{"title":"title2"}]')
;
SELECT *
FROM tbl, jsonb_array_elements(js) AS job
WHERE job->>'title' = 'title2';
See:
But for big tables it's a lot more efficient to filter with the jsonb
contains operator @>
:
SELECT *
FROM tbl
WHERE js @> '[{"title":"title2"}]';
Or with a SQL/JSON path expression:
SELECT *
FROM tbl
WHERE js @? '$[*] ? (@.title == "title2")';
The last two can use a GIN index like:
CREATE INDEX tbl_js_gin_idx ON tbl USING gin (js jsonb_path_ops);
See: