Heading image for post: Querying for JSON Arrays in Postgres

Querying for JSON Arrays in Postgres

Profile picture of Craig Hafer

A few months ago I wrote a blog post that talks about Dealing with nested JSON objects in PostgreSQL. In there I talk about using the Stabby, Waffle Cone, and Penguin operators to navigate through a JSON object. In this post, I want to talk about what to do when that JSON object contains an array.

To keep this post simple, we're going to create a new table that has a jsonb column in it, add data to the column, and then navigate through it to get the data we want. If you already have your own data you want to navigate through, feel free to skip to the navigating portion. As a bonus at the very end, I will go over using the jsonb_array_elements postgres function.

Create a new table

Let's create a simple table that just has a jsonb column, so that we can test this out. We can do that with the following statement:

create table your_table_name (jsonb_column_name jsonb);

Add data to the column

Now that we have the table setup, let's populate it with some data.

INSERT INTO your_table_name (jsonb_column_name)
VALUES ('{"key-1": [{"sub-key-1": "sub-value-1"},{"sub-key-2": "sub-value-2"}], "key-2": "value-2"}')
;

Here is a visual representation of this JSON object:

{
  "key-1": 
    [
      {"sub-key-1": "sub-value-1"},
      {"sub-key-2": "sub-value-2"}
    ], 
  "key-2": "value-2"
}

Navigate through the data

First, let's verify that our data is indeed where we expect it to be. We can check that by running this:

select jsonb_column_name from your_table_name;

We should see that it returns something similar to this:

image

Next, using the Stabby (->) operator, let's traverse through this column.

select jsonb_column_name->'key-1' as key_1 from your_table_name;

That will return to us the following:

image

Now, for the part we've all been waiting for! To traverse through the array, we simply use the Stabby operator again, "stabbing" whatever index of the array we want!

select 
jsonb_column_name->'key-1'->0 as sub_key_1, 
jsonb_column_name->'key-1'->1->'sub-key-2' as sub_value_2 
from your_table_name
;

This query should return the following:

image

As you can see, you can continue navigating through the objects inside the array, like normal, just using the Stabby operator after the array index.

This also works with negative numbers, to navigate from the end of the array, starting with -1.

select jsonb_column_name->'key-1'->-1 as sub_key_2 from your_table_name;

Which can be seen here:

image

If you grab from an index that is out of bounds, it will just return null.

select jsonb_column_name->'key-1'->999 as out_of_bounds_example from your_table_name;

Which can be seen here:

image

Summary

In this post we covered the fact that if there is an array in your JSON object, you simply use the Stabby operator to dig into the array, by its index. We saw that we are able to grab from the end of the array using a negative index. We also saw that going out of bounds in the array returned null.

Bonus

As promised, I will now go over using the Postgres function jsonb_array_elements.

Let's say we needed to iterate over each element in the array from above. We wouldn't want to do something like this:

select jsonb_column_name->'key-1'->0, jsonb_column_name->'key-1'->1 from your_table_name

This would obviously get very tedious, even if we were building it out programmatically. So instead, we can use jsonb_array_elements on our jsonb array to do all of that for us!

To make this example make more sense, let's use some data that you might actually see in a real application. Here is the JSON data we will be using for this example:

{
  "users": [
    {"id": "91273", "name":"brian", "email":"brian@example.com"},
    {"id": "71867", "name":"dom",   "email":"dom@example.com", "sibling_ids": ["42680"]},
    {"id": "42680", "name":"mia",   "email":"mia@example.com", "sibling_ids": ["71867"]}
  ]
}

Here, we use our jsonb column to hold an array of users, with some information about the users.

As you can see, some data is specific to each user.

Example

So, to give us each element in the array we would run this query:

select jsonb_array_elements(jsonb_column_name->'users') as users from your_table_name;

Which would return to us:

image

Here is an example grabbing multiple points of data:

select
jsonb_array_elements(jsonb_column_name->'users')->>'id' as id,
jsonb_array_elements(jsonb_column_name->'users')->>'name' as name
from your_table_name
;

Which would return to us:

image

Lastly, if data is specific only to certain elements of the array, it will just return null for indices that it doesn't apply to.

select 
jsonb_array_elements(jsonb_column_name->'users')->>'id' as id,
jsonb_array_elements(jsonb_column_name->'users')->'sibling_ids' as sibling_ids 
from your_table_name
;

Which can be seen here:

image


Photo by: Rico Van de Voorde on Unsplash

  • Adobe logo
  • Barnes and noble logo
  • Aetna logo
  • Vanderbilt university logo
  • Ericsson logo

We're proud to have launched hundreds of products for clients such as LensRentals.com, Engine Yard, Verisign, ParkWhiz, and Regions Bank, to name a few.

Let's talk about your project