30

Recently upgraded to using PostgreSQL 9.3.1 to leverage the JSONfunctionalities. In my table I have a json type column that has a structure like this:

{
 "id": "123",
 "name": "foo",
 "emails":[
 {
 "id": "123",
 "address": "somethinghere"
 },
 {
 "id": "456",
 "address": "soemthing"
 }
 ]
} 

This is just dummy data for the purpose of the question.

Is it possible to query for a specific item in the emails array based on the id?
Pretty much: "return email where id=123)"?

Erwin Brandstetter
668k159 gold badges1.2k silver badges1.3k bronze badges
asked Oct 24, 2013 at 13:59

4 Answers 4

59

For Postgres 9.4+ see adamc's later answer. Or:

Original answer for Postgres 9.3

Yes, that's possible:

SELECT *
FROM tbl t, json_array_elements(t.json_col->'emails') AS elem
WHERE elem->>'id' = 123;

tbl being your table name, json_col the name of the JSON column.

See also:

About the implicit CROSS JOIN LATERAL:

Index to support this kind of query:

answered Nov 8, 2013 at 21:21
Sign up to request clarification or add additional context in comments.

2 Comments

This is the best answer I have seen for this type of question so far.
@ErwinBrandstetter Sorry for off-top, but could you please help with this issue: stackoverflow.com/q/49532773 (Thanks in advance!)
10

With a JSONB column in Postgres 9.4+ you can use the contains operator @> to query for an element in an array:

SELECT * FROM jsontest WHERE data @> '{ "emails": [{ "id": "123" }] }';

See Query for array elements inside JSON type for more details.

Here is a working example:

CREATE TABLE jsontest(data JSONB NOT NULL);
INSERT INTO jsontest VALUES (
 '{
 "name": "foo",
 "id": "123",
 "emails": 
 [
 {
 "address": "somethinghere",
 "id": "123"
 },
 {
 "address": "soemthing",
 "id": "456"
 }
 ]
 }'
);
SELECT * FROM jsontest WHERE data @> '{ "emails": [{ "id": "123" }] }';
data
----
{"id": "123", "name": "foo", "emails": [{"id": "123", "address": "somethinghere"}, {"id": "456", "address": "soemthing"}]}

(1 row)

answered Jan 30, 2017 at 1:54

2 Comments

how to delete address by id 123 ?
delete FROM jsontest WHERE data @> '{ "emails": [{ "id": "123" }] }';
3

Came across this post and found that you can directly query on table like this:

SELECT *
FROM table_name, json_array_elements(json_column) AS data
WHERE data->>'id' = 123;

Omitting this part:

json_array_elements(t.json_col->'emails')
answered Aug 8, 2016 at 11:45

1 Comment

this is super super useful I have been struggling with CTE to try and make it work, and this just solves my need beautifully. Thanks!
-1

You can do it as simple as :

SELECT * FROM table WHERE emails->>'id' = '123';

it seems you store the id as string, if it was an integer you can do it like this :

SELECT * from table WHERE cast(emails->>'id' as integer ) = 123 ;

or you can get all the rows with id> 10

SELECT * from table WHERE cast(emails->>'id' as integer ) > 10 ;
answered May 12, 2015 at 13:01

1 Comment

I've tried this on Postgres 9.4.4 and it doesn't work:

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.