Reputation: 57
I'm trying to pull elements from JSONB column. I have table like:
id NUMBER
data JSONB
data structure is:
[{
"id": "abcd",
"validTo": "timestamp"
}, ...]
I'm querying that row with SELECT * FROM testtable WHERE data @> '[{"id": "abcd"}]'
, and it almost works like I want to.
The trouble is data
column is huge, like 100k records, so I would like to pull only data elements I'm looking for.
For example if I would query for
SELECT * FROM testtable WHERE data @> '[{"id": "abcd"}]' OR data @> '[{"id": "abcde"}]'
I expect data column to contain only records with id abcd or abcde. Like that:
[
{"id": "abcd"},
{"id": "abcde"}
]
It would be okay if query would return separate entries with single data record.
I have no ideas how to solve it, trying lot options since days.
Upvotes: 0
Views: 2236
Reputation: 92
Didn't quite get your question.Are you asking that the answer should only contain data column without id column .Then I think this is the query:
Select data from testtable where id="abcd" or id="abcde";
Upvotes: 0
Reputation: 794
To have separate output for records having multiple matches
with a (id, data) as (
values
(1, '[{"id": "abcd", "validTo": 2}, {"id": "abcde", "validTo": 4}]'::jsonb),
(2, '[{"id": "abcd", "validTo": 3}, {"id": "abc", "validTo": 6}]'::jsonb),
(3, '[{"id": "abc", "validTo": 5}]'::jsonb)
)
select id, jsonb_array_elements(jsonb_path_query_array(data, '$[*] ? (@.id=="abcd" || @.id=="abcde")'))
from a;
Upvotes: 1
Reputation:
You will need to unnest, filter and aggregate back:
select t.id, j.*
from testtable t
join lateral (
select jsonb_agg(e.x) as data
from jsonb_array_elements(t.data) as e(x)
where e.x @> '{"id": "abcd"}'
or e.x @> '{"id": "abcde"}'
) as j on true
With Postgres 12 you could use jsonb_path_query_array()
as an alternative, but that would require to repeat the conditions:
select t.id,
jsonb_path_query_array(data, '$[*] ? (@.id == "abcd" || @.id == "abcde")')
from testtable t
where t.data @> '[{"id": "abcd"}]'
or t.data @> '[{"id": "abcde"}]'
Upvotes: 0