I have Postgres JSONB array of objects, looking like this :
'[
{
"skillId": "1",
"skillLevel": 42
},
{
"skillId": "2",
"skillLevel": 41
}
]'
This JSONB is a function argument.
What is the most efficient way to retrieve skillLevel
for skillId = "1"
.
I've tried to play with jsonb_array_elements
but everything I've done so far is looking really messy.
Querying the JSON document PostgreSQL has two native operators -> and ->> to query JSON documents. The first operator -> returns a JSON object, while the operator ->> returns text. These operators work on both JSON as well as JSONB columns. There are additional operators available for JSONB columns.
In Postgres, if you select a key that does not exist it will return null. so u can check the existence of a key by checking the null value of that key.
JSONB stands for “JSON Binary” or “JSON better” depending on whom you ask. It is a decomposed binary format to store JSON. JSONB supports indexing the JSON data, and is very efficient at parsing and querying the JSON data. In most cases, when you work with JSON in PostgreSQL, you should be using JSONB.
In Postgres 9.4+ use the function jsonb_array_elements()
in a lateral join:
select (elem->>'skillLevel')::int as skill_level
from my_table
cross join jsonb_array_elements(json_col) elem
where elem->>'skillId' = '1';
You can implement the idea in a simple function, e.g:
create or replace function extract_skill_level(json_data jsonb, id int)
returns integer language sql as $$
select (elem->>'skillLevel')::int
from jsonb_array_elements(json_data) elem
where elem->>'skillId' = id::text
$$;
select extract_skill_level(json_col, 1) as skill_level
from my_table;
In Postgres 12+ you have a nice alternative in the form of jsonb path functions:
select (
jsonb_path_query(
json_col,
'$[*] ? (@.skillId == "1")'
)->'skillLevel'
)::int as skill_level
from my_table;
Db<>Fiddle.
Read more about JSON Functions and Operators.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With