Postgres Unstructured Database using JSONB: Mastering the Art of Code
I recently ran into a very specific problem in my use-case.
Story behind the problem:
We had developed a backend with dynamic APIs and its corresponding queries to be run on the customer's database. Only problem being, we had no idea what the database might look like.
So I created a table that looked like this:
Endpoint | Query | Description |
/getAllAccounts | select * from accounts | get all data from accounts table |
/getAccountsByRoleType | select * from accounts where role_type=[role] | query the table according to role and get the data |
And I created a backend using Springboot and JAVA to get required data for queries that had [parameter] in them and process them accordingly. Hence, for any query, I could return its corresponding queried data in JSON format.
So the endpoint for parameterized queries would look like this:
/getAccountsByRoleType?role=Admin
Good, now thats done, I would need to collect this data and save it in my own Database(future needs, don't ask why).
So, now I have to save the data from their table into my own, the structure of the data being dynamic and unknown. So, I guess we are left with only one option - nosql database.
Whats standing in the way? Well, I am using Postgres for the rest of my applications, hence there is a dependency there.
Now we come to the problem of saving unstructured data in a structured DB. Lets begin.
Scouring the net, I decided on a few ways we could implement this:
Option 1:
We could save the unstructured data as JSON string in a column.
That seems easy enough, although we will have to pull all data and iterate through every row to find specific queries within each JSON.
Quite a lot of overhead for a data dump of about 70K to 80K records. Lets keep this aside for now.
Option 2:
Solution that I found for quick filtering queries? We can use Postgres's JSONB datatype for this use case. JSONB or Binary JSON saves the Object as a binary and indexes all the keys at the time of insertions. So, this indexing adds a minimal overhead while insertions. Tests suggest it is very insignificant at 70K to 80K records to worry about.
This seems like a viable option. Lets look at how to use this.
How to use JSONB with Java Springboot project?
1 | CREATE TABLE karnage(id int, data JSONB, created_date Date); |
1 2 3 4 5 | <dependency> <groupId>com.vladmihalcea</groupId> <artifactId>hibernate-types-52</artifactId> <version>${hibernate-types.version}</version> </dependency> |
git Link: Hibernate Types git
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | import com.vladmihalcea.hibernate.type.json.JsonBinaryType; @Entity @Table(name="karnage") @TypeDef(name = "jsonb", typeClass = JsonBinaryType.class) public class KarnageEntity{ @Id @GeneratedValue(strategy=GenerationType.AUTO) //Only Needed if ID is @Column(name="ID") //handled by persistence library private long id; @Type(type = "jsonb") @Column(name="DATA") private String data; //Might be a String but we will push JSONObject @Column(name="created_date") private Date createdDate; } |
How to Filter Data from the data column and use the set up as an unstructured database?
To filter the data from the JSONB data column, we need a normal query albeit, with a little twist.
Lets look at how a JSONB query looks like:-
SELECT * FROM karnage WHERE and data ->> 'key'='value';
Select data ->> 'key' from karnage;
So, we need to search for a value to a key using the "data->>" for the JSONB column.
Note:
If we use ->>, we will only return the result as text. To return JSONB object, use ->
So there we have it, the complete guide to using JSONB and handling unstructured data in a structure database with Springboot.
Thanks for reading!
Comments
Post a Comment