I have an example table to demonstate a problem.
create table myteble (
id serial primary key ,
metadata jsonb
-- other fields
-- ......
)
metadata
is a jsonb column, and it might and most likely will contain some portion of semi-arbitrary data. What I want to do during update, create inside top level of this column data like {api_cnt: {'some_api_name': 1, 'other_api_name': 2, ...}
and increment this counter (+1) on each update (that is 1+1 -> 2, 2+1 -> 3, etc). The important aspect is that this key’s api_cnt
or (and) nested keys (like some_api_name
for example) might not exist beforehand.
The closest I could get there is the following:
update myteble
set metadata = jsonb_set(metadata, '{api_cnt}', '2', true)
where id = 1;
But I don’t know how to create nested record api_cnt -> some_api_name
and how to increment value based on itself (new_value = old_value + 1)
Example 1 where keys do not exist beforehand:
--PSEUDOCODE
id=1, metadata = {'inner something': [1,2,3,4,5]}
update myteble set ...{api_cnt: {'some_api_name': increment+1, 'other_api_name': increment+1} ... where id = 1
RESULT -- {'inner something': [1,2,3,4,5], {api_cnt: {'some_api_name': 1, 'other_api_name': 1}}
Example 2 where keys do exist already:
--PSEUDOCODE
id=1, metadata = {'inner something': [1,2,3,4,5], {api_cnt: {'some_api_name': 1, 'other_api_name': 8}}
update myteble set ...{api_cnt: {'some_api_name': increment+1, 'other_api_name': increment+1} ... where id = 1
RESULT -- {'inner something': [1,2,3,4,5], {api_cnt: {'some_api_name': 2, 'other_api_name': 9}}
2
Answers
PostgreSQL 14 and higher supports indexes for access to jsonb:
I can write simple plpgsql function:
at the end, you don’t need plpgsql function:
(1 row)
Attention!: all PostgreSQL values are immutable. Any update is implemented as an copy of value, then this copied value is modified and stored. Previous value is destroyed. Modification of any
jsonb
value is significantly slower than just modification of numeric column, and it can be very slow, if thisjsonb
value is large or large and indexed. Non atomic types like json, jsonb are not too good for frequently modified values. When are short, then it can work, but when are longer (what is longer depends on hw), then it can be pretty slow (against relational model).