jsonb : find row by array object attribute

Started by Rory Campbell-Langeover 7 years ago4 messagesgeneral
Jump to latest
#1Rory Campbell-Lange
rory@campbell-lange.net

With a table like this:

Table "public.x"
Column | Type | Modifiers
--------+-------+-----------
j | jsonb |

and data like this:
j
--------------------------------------------------
{"a": 1, "people": [{"id": 2002}, {"id": 2004}]}
{"a": 3, "people": [{"id": 2003}, {"id": 2005}]}
(2 rows)

I'd like to be able to find any row with a particular people id
attribute.

I can do it explitly like this:

select * from x where j->'people'->0->'id' = '2003'::jsonb;

j
--------------------------------------------------
{"a": 3, "people": [{"id": 2003}, {"id": 2005}]}
(1 row)

but that doesn't help if I need to find if any person matches the id
attribute I'm looking for.

I can get part of the way by searching like this:

=> select * from (
select jsonb_array_elements(j #>'{people}') as jae from x
) y
where jae->'id' = '2002'::jsonb;

jae
--------------
{"id": 2002}
(1 row)

but I can't work out how to return the whole row containing a desired
people id value.

Thanks for any help
Rory

#2Tom Lane
tgl@sss.pgh.pa.us
In reply to: Rory Campbell-Lange (#1)
Re: jsonb : find row by array object attribute

Rory Campbell-Lange <rory@campbell-lange.net> writes:

... I can't work out how to return the whole row containing a desired
people id value.

Something like this, maybe?

=# select * from x where
'2003'::jsonb in (select jsonb_array_elements(j #>'{people}')->'id');
j
--------------------------------------------------
{"a": 3, "people": [{"id": 2003}, {"id": 2005}]}
(1 row)

It's not too efficient though :-(

regards, tom lane

#3Andrew Gierth
andrew@tao11.riddles.org.uk
In reply to: Rory Campbell-Lange (#1)
Re: jsonb : find row by array object attribute

"Rory" == Rory Campbell-Lange <rory@campbell-lange.net> writes:

Rory> and data like this:
Rory> j
Rory> --------------------------------------------------
Rory> {"a": 1, "people": [{"id": 2002}, {"id": 2004}]}
Rory> {"a": 3, "people": [{"id": 2003}, {"id": 2005}]}
Rory> (2 rows)

Rory> I'd like to be able to find any row with a particular people id
Rory> attribute.

where j @> '{"people":[{"id":2003}]}'

(meaning: j contains a key "people" whose value is an array containing
an element {"id":2003})

Since @> can use GIN indexes, you should usually try and find a search
condition using it before resorting to playing with -> or expanding out
array values.

--
Andrew (irc:RhodiumToad)

#4Andrew Gierth
andrew@tao11.riddles.org.uk
In reply to: Andrew Gierth (#3)
Re: jsonb : find row by array object attribute

"Andrew" == Andrew Gierth <andrew@tao11.riddles.org.uk> writes:
"Rory" == Rory Campbell-Lange <rory@campbell-lange.net> writes:

Rory> and data like this:
Rory> j
Rory> --------------------------------------------------
Rory> {"a": 1, "people": [{"id": 2002}, {"id": 2004}]}
Rory> {"a": 3, "people": [{"id": 2003}, {"id": 2005}]}
Rory> (2 rows)

Rory> I'd like to be able to find any row with a particular people id
Rory> attribute.

Andrew> where j @> '{"people":[{"id":2003}]}'

Andrew> (meaning: j contains a key "people" whose value is an array
Andrew> containing an element {"id":2003})

or to be more precise: j is an object containing a key "people" whose
value is an array containing an element which is an object containing a
key "id" with value 2003

i.e. {"a":3, "people": [{"id":2003,"blah":123},{"id":2004}]} would
match the condition too.

--
Andrew (irc:RhodiumToad)