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)"?

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:

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)

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')

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  ;

1 Comment

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

Your Answer

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.