-
Notifications
You must be signed in to change notification settings - Fork 3
Guide
After this guide, I guarantee, you will never be required to see the documentation of this database. This guide will explain everything step-by-step with examples. So let's begin with the index.
It would be best if you see JavaDocs and acknowledgment first before diving into the guide. Anyway, let's get started.
To initialize database, call static getInstance()
method of class Clorem
. This will initialize the database with the provided name and then return a singleton instance of the class.
Example:
Node root = Clorem.getInstance(databaseDir,"demoDB").getDatabase();
This getDatabase()
return root node of the database.
Note: For android, you must pass context.getDataDir()
or any other application private writable direcotry.
after being initializing and getting the root node, let's now explore the core part of the database.
To create a key-value pair in the current node, use put()
method. This will update the value if the key already exist.
Example:
root.put("key",value);
root.put("key2",value2);
root.put("key3",value3);
root.commit(); // This is important
Note* : You have to call commit()
after putting values. Otherwise, no data would be committed to the database. Avoid calling commit() frequently, try to call it in the last (before your program exits) or in onStop()
in case of android
To save an object or a list, pass that object/list in the put()
method like this:
root.put("user1",new User("Rahil",15,true));
root.put("list1",playersList);
root.put(mapOfData)
Note: Any changes made, before committing, to the objects or list that are passed in put()
method gets reflected in the database automatically
To create/get a node use, node()
method. This will return you that new node instance.
Example:
Node newNode = root.node("newNode");
newNode.put("key",value);
// ... Operations on this new node.
You could also use the Relative path of the node in the node()
method. For example, passing "newNode/superNode/lastNode" will return lastNode. This way you can get deeply nested nodes without going there one by one.
To read a value from the database, first, go into that node & then call getX()
passing the key of the data. Here x is the data type you want to get.
Example:
String string = root.getString("key", null); // returns data from root node
String string = root.node("newNode").getString("key", null); // returns data from "newNode" node
Map<String,Object> data = root.getData(); // Gets all the key-value mappings in the form of *Map*
You can delete any node which is a direct child of the parent one. Like to delete a node 'A' , you need to call delete("A")
from its parent node.
Example:
newNode.delete("nodeA") // To delete this nodeA & its content.
newNode.removeItem("list1",5); // To remove a particular item from the list
db.delete() // deletes the whole database.
In this example, we will store a few details of Contributors.
Node node = Clorem.getInstance(this, "demoDB").getDatabase().node("contributor");
node.node("Rahil")
.put("instagram", "@x__coder__x")
.put("github", "@ErrorxCode")
.put("website", "xcoder.tk");
node.node("Shubam")
.put("instagram", "@weshubh")
.put("github", "@shubhamp98")
.put("website", "shubhamp98.github.io");
node.node("Anas")
.put("instagram", "anas.ansari46")
.put("github", "@anas43950")
.put("website", "x-code.ml")
.commit();
This will result in a structure like this:-
{
"contributor": {
"Anas": {
"github": "@anas43950",
"website": "x-code.ml",
"instagram": "anas.ansari46"
},
"Shubam": {
"github": "@shubhamp98",
"website": "shubhamp98.github.io",
"instagram": "@weshubh"
},
"Rahil": {
"github": "@ErrorxCode",
"website": "xcoder.tk",
"instagram": "@x__coder__x"
}
}
}
You can also query data from the database as you do in Sqllite. You can run queries on nodes with some conditions. There are 2 types of queries,
In this type of query, you first need to go on the grandparent node of the child you wish to Query. For example, if I have to get the name of the user whose username is "weshubh" then, I have to call a query on the "contributor" node.
List<String> list1 = node.query().whereContains("instagram", "shub"); // [shubam]
List<String> list2 = node.query().whereGreater("age", 18); // Hypothetical example
Use this query when you know the grandparent node (contributor in this case) of the data and your data node has an extra wrapper node.
This query is used for sorting complex data structures. In this type of query, Given a node, you can find any node under it doesn't matter how deeply nested it is. To use this query, create an object of it passing the node from where to start querying data. The data must be inside of this node or the parent of data must be inherited from the node which you have passed. Example:
BigQuery query = new BigQuery(contributor);
Node[] nodes = query.where(map -> ((String) map.getOrDefault("instagram", "")).startsWith("@"));
Here contributor is our contributor
node (You can also pass parent or parent-of-parent of contributor node). This will bring all the nodes which have their Instagram username starting with '@'.
Use this query, when your data does not have an extra wrapper node and is deeply nested. You don't need to go to the grandparent node for querying data, you can start from anywhere. This will return you exact nodes which meet the condition and contain the required data.
You can also create queries somewhat from SQL queries. For example, to list all the nodes which have age > 18, the query would be like this:
Where age > 18
. Now pass this to node.query().fromQuery(String)
method. *This must also be called from grandparent node i.e contributors in this case.
The syntax for the query is : Where {property} {comparator} {value} limit {number} where,
property is the field on which you have to query data. This can be any field of the node
comparator is the relational operation criteria for checking the value against. Valid options are < , > , = , contains
value is the value by which to check against. This is a number for the numeric field and a string for the alphabetic field
number The max no. of results you want to retrieve. This is optional (leave the 'limit' onwards blank)
Consider the following database:
{
"users": {
"user1": {
"name": "John",
"age": 30,
"is_married": false
},
"user2": {
"name": "Mary",
"age": 25,
"is_married": true
},
"user3": {
"name": "Mike",
"age": 27,
"is_married": false
}
}
}
The followings are the different types of queries on the basis of criteria,
- To get all the users who are older than 25:
where age > 25
- To get 1 unmarried user :
where is_married = false limit 1
- To get users whose names contain 'M':
where name contains 'M'
- To get a user whose name is 'Jhon':
where name = 'John'
To get users whose Instagram username contains 'a' in it :
String query = "where instagram contains '@' limit 2";
List<Node> nodes = contributorNode.query().fromQuery(query);
for (Node node : nodes) {
System.out.println(node.getData());
}
This will result in output somewhat like this:
"Anas": {
"github": "@anas43950",
"website": "x-code.ml",
"instagram": "anas.ansari46"
},
"Shubam": {
"github": "@shubhamp98",
"website": "shubhamp98.github.io",
"instagram": "@weshubh"
}
This will only bring us Node of Anas and Shubam because we have limited the result to 2.
If your query is linear and you know the grandparent node of the querying node, you should use Simple query. If your query is non-linear or even linear and the node does not have an extra wrapper, then you must use Big query.
Consider the following data structure:
"posts1": {
"stats": {
"views" : 500,
"likes" : 250,
"shares": 170,
},
"isReel":true,
"tags" : ["nosql","databases","clorabase","clorem"]
},
"posts2": {
"stats": {
"views" : 2000,
"likes" : 400,
"shares": 750,
},
"isReel":false,
"tags" : ["java","query","sorting"]
}
Here, each post has an extra 'stats' node that wraps the whole data and also we know their grandparent node (root in this case). We want to query posts whose likes are greater than 500. So we will use simple query in this case.
List<String> nodes = root.query().whereGreater("stats/views", 500); // returns [post2]
for (String node : nodes) {
Node post = root.node(node);
// TODO user...
}
And if the structure was like:
"posts": {
"posts1": {
"views" : 500,
"likes" : 250,
"shares": 170,
"isReel":true,
"tags" : ["nosql","databases","clorabase","clorem"]
},
"posts2": {
"stats": {
"video": {
"views" : 2000,
"likes" : 400,
"shares": 750,
"id":45653466462
},
"comment": {
"views" : 20,
"likes" : 8,
"id":87622335565
}
},
"isReel":false,
"tags" : ["java","query","sorting"]
}
}
As you can see, this is a non-linear data structure (Each post has a different no. of nested nodes). In post1, data is located in "/post1" and "/post2/stats/video" in post2. So we have to use Big query in this case. Example:
BigQuery query = new BigQuery(posts);
Node[] nodes = query.where(map -> ((boolean) map.getOrDefault("isReal",true));
These nodes are the exact nodes that meet the condition. In this case, it will include the video node present in post1.
If you have linear data and know grandparent node, use Simple query else use Big query. The big query is a little slower than a Simple query but it can find any nested node from the root of the database. If you are using a Big query on non-linear data, you should include a unique identifier like id, parent name, etc. in the node.
You can also see the structure of the database in the form of JSON. To get this JSON string, use getDatabaseAsJson()
method of the database class.
String structure = db.getDatabaseAsJson();
System.out.println(structure); // Prints the structure as shown above.
If you get into an error/exception (mostly runtime), you can get the reason for the exception using getReason()
method. Check Reasons ENUM for all reasons.
Now you have mastered the cloremDB. It's time to contribute to this project now. Any queries? see the clorem tag on StackOverflow