I have gone through various JSONB tutorials:
Consider the following example.
There is a table called plans
. It has the following columns:
id
(integer, auto-incrementing primary key).name
(string).structure
(jsonb).The structure column has a regular JSON object having the following structure:
{
"some_unique_id": {
"key1": "valueA", // Fixed key name.
"key2": "valueB" // Fixed key name.
},
"another_unique_id": {
"key1": "valueC", // Fixed key name.
"key2": "valueB" // Fixed key name.
},
... // can go on up to a 1000 items.
}
Note: The outermost keys are dynamic. They change for every item. The values are just regular JSON objects. Nothing special.
I use UUIDs as the keys in the structure so it is easy to lookup and retrieve a specific value, if I know its UUID.
The other option is to make my structure an array of objects (and put the UUID as a value inside every object) like the following:
[
{
"uuid": "some_unique_id",
"key1": "valueA", // Fixed key name.
"key2": "valueB" // Fixed key name.
},
{
"uuid": "another_unique_id",
"key1": "valueC", // Fixed key name.
"key2": "valueB" // Fixed key name.
},
... // can go on up to a 1000 items.
]
In this latter approach, to retrieve a particular object using its UUID, I would have to loop through the entire array and match the uuid
key of every object.
So, I chose the first approach.
The table has 3 records. For this question, the value of the id
and name
columns are not important.
The actual values of the structure
column in the 3 records are as below.
Record 1:
{
"bab6246d-802c-4b80-af41-ab15fd1541b4": {
"name": "Sanskrit",
"children_uuids": [
"fa42b4b2-a958-42f1-af33-314e8e1fb6a6",
"3aeeadfe-6ad4-4229-85a5-5de030c08014"
],
"is_invisible_node": true,
"tags": [
"paper",
"course_paper"
],
"type": "course_paper"
},
"dbc33473-8453-4cf9-8ecf-d8013283b0d8": {
"name": "French",
"children_uuids": [
"4bf65ff9-3b11-42d5-a744-adcd1fd5a953"
],
"is_invisible_node": true,
"tags": [
"paper",
"course_paper"
],
"type": "course_paper"
}
}
Record 2:
{
"ed6164d0-fdc0-4259-90a5-fd60d9d716dc": {
"name": "Pen and Paper Assessment 1",
"children_uuids": [
],
"is_invisible_node": false,
"tags": [
"paper",
"assessment"
],
"type": "assessment"
},
"059d0116-bca2-49f1-b333-58c4dbec8566": {
"name": "Content",
"children_uuids": [
],
"is_invisible_node": false,
"tags": [
"paper",
"assessment"
],
"type": "assessment"
}
}
Record 3:
{
"63619c7f-fa73-49af-9df5-4be1eb38cee5": {
"name": "Q12",
"children_uuids": [
],
"is_invisible_node": true,
"tags": [
"paper",
"regular_paper"
],
"type": "regular_paper"
},
"56eed164-17f7-48e9-b3ce-b5b469e8cb0e": {
"name": "Q13",
"children_uuids": [
],
"is_invisible_node": false,
"tags": [
"paper",
"regular_paper"
],
"type": "regular_paper"
},
"69d202c1-5c23-412f-860d-1a5d705c31b3": {
"name": "Q14",
"children_uuids": [
],
"is_invisible_node": false,
"tags": [
"paper",
"regular_paper"
],
"type": "regular_paper"
}
}
Now, how do I write queries to do the following two things?
is_invisible_node
property set to true.regular_paper
as one of its tags
.Thank you for reading this far! Any help would be appreciated.
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.
Json processes input faster than jsonb as there is no conversion involved in this. Jsonb converts the JSON data into the binary form so it has slightly slower input due to the binary conversion overhead. There is no change in the Schema design while working with JSON.
PostgreSQL provides two native operators -> and ->> to help you query JSON data. The operator -> returns JSON object field as JSON. The operator ->> returns JSON object field as text.
With JSON in PostgreSQL, you can have a solution to your complex problem. PostgreSQL is a high-performing, open-sourced object-relational database with two JSON data storage types, JSON and JSONB. JSONB (JavaScript Object Notation Binary) offers seamless and fast data exchange over a network in a small and simple-to-use data format.
Let’s say we have to query a user table with a metadata JSONB column on a PostgreSQL 9.5+ database. 1. Select items by the value of a first level attribute (#1 way) You can query with the @> operator on metadata. This operator can compare partial JSON strings against a JSONB column. It’s the containment operator.
For example, the following jsonpath expression is valid in PostgreSQL: There are minor differences in the interpretation of regular expression patterns used in like_regex filters, as described in Section 9.15.2.2. 9.15.2.1. Strict and Lax Modes When you query JSON data, the path expression may not match the actual JSON data structure.
Use it if you want to query a simple field in a JSONB column. You might add a B-tree index on metadata->>'country'. 3. Select item attribute value Once again, the ->> operator gets a JSON object field as text. Just use directly it in the SELECT. 4. Select only items where a particular attribute is present
I want to get all records which contain any objects with the is_invisible_node property set to true.
Use jsonb_each()
to retrieve objects on the second level:
select id, uuid.key uuid
from
plans,
jsonb_each(structure) uuid
where (value->>'is_invisible_node')::boolean;
id | uuid
----+--------------------------------------
1 | bab6246d-802c-4b80-af41-ab15fd1541b4
1 | dbc33473-8453-4cf9-8ecf-d8013283b0d8
3 | 63619c7f-fa73-49af-9df5-4be1eb38cee5
(3 rows)
or
select distinct id
from
plans,
jsonb_each(structure) uuid
where (value->>'is_invisible_node')::boolean;
id
----
1
3
(2 rows)
I want to get all objects which contain regular_paper as one of its tags.
The json object tags
is an array, so unnest it with jsonb_array_elements_text()
:
select uuid.key uuid
from
plans,
jsonb_each(structure) uuid,
jsonb_array_elements_text(value->'tags') tag
where tag = 'regular_paper';
uuid
--------------------------------------
56eed164-17f7-48e9-b3ce-b5b469e8cb0e
63619c7f-fa73-49af-9df5-4be1eb38cee5
69d202c1-5c23-412f-860d-1a5d705c31b3
(3 rows)
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