visit
Recently I had to write a script, which should’ve changed some JSON data structure in PSQL database. Basically, I had to parse one value and put that in another field. Since, I didn’t have a lot of experience with SQL or PSQL for that matter, reading and understanding documentation for my specific use cases took a little too long.
For starters, I need a place where I can fiddle with databases, and serendipitously enough I found dbfiddle. You can check out the queries from this article there.
CREATE TABLE jsonb_exp (
id serial primary key,
data jsonb
);
INSERT INTO jsonb_exp (data) VALUES
('{"data":{"1":{"items":[{"name":"John"},{"name":"Jack"}]},"2":{"items":[{"name":"John Dorian"},{"name":"Jack Sparrow"}]},"3":{"items":[{"name":"Tom Cruise"},{"name":"somerandomtext"}]},"5":{"items":[{"name":"Tom Cruise"}]}},"property":"Some string"}'),
('{"data":{"4":{"items":[{"name":"Maria"},{"name":"Jack"}]},"6":{"items":[{"name":"Jack Jackson"},{"name":"Thomas ---"}]},"7":{"items":[{"name":"-"},{"name":"somerandomtext"}]},"15":{"items":[{"name":"hello"}]}},"property":"Some string"}'),
('{"a": "b", "c": [1, 2, 3]}'
SELECT * from jsonb_exp;
-> returns jsonb
->> returns text
Not sure, what type you’re working with, you can use pg_typeof.
SELECT data->>'data' as data, pg_typeof(data->'data'), pg_typeof(data->>'data') from jsonb_exp where data->>'data' IS NOT NULL;
jsonb_path_query()
SELECT id, data, item FROM jsonb_exp t, jsonb_path_query(data->'data', '$.*.items[*]') as item
WHERE data->'data' IS NOT NULL AND item->>'name'='Jack';
Unpacking. Let’s first look at the jsonb_path_query
query, everything else is just the support around it to demonstrate what we did.
Reading ‘$..items[]’, here is how you can read it. $ - the object itself, it can contain a key we don’t know - mark it with an asterisk. Inside of that, we want to look for property items, which is an array, and using [*] we say, that we want every item inside that array.
The comma in the query is just an implicit cross-join, not super relevant to JSONB methods.
SELECT id, data, jsonb_path_query(data->'data', '$.*.items[*] ? (@.name == $name)', '{"name": "John"}') FROM jsonb_exp
WHERE data->'data' IS NOT NULL;
SELECT id, data, jsonb_path_query(data->'data', '$.*.items[*] ? (@.name like_regex "^John")') FROM jsonb_exp
WHERE data->'data' IS NOT NULL;
Lead image by on Unsplash