Chapter 2. RethinkDB Query Language

ReQL means RethinkDB query language. It offers a powerful and easy way to perform operations on JSON documents. It is one of the most important parts of the RethinkDB architecture. It is built on three important principles: embedding ReQL in a programming language, ReQL queries being chainable, and ReQL queries being executed on the server.

Here is a list of topics we are going to cover, along with the mentioned principles:

  • Performing conditional queries
  • ReQL queries are chainable
  • ReQL queries are executed on a server
  • Traversing over nested fields
  • Performing string operations
  • Performing MapReduce operations
  • Calling HTTP APIs using ReQL
  • Handling binary objects
  • Performing JOINS
  • Accessing changefeed (real-time feed) in RethinkDB
  • Performing geolocation operations
  • Performing administrative operations

Let us look over each one of them.

Embedding ReQL in a programming language

RethinkDB provides client drivers for various programming languages. To explain, I am going to consider Node.js, and the steps are as follows:

  1. You can start the ReQL exploration journey by connecting to the database.
  2. Install the RethinkDB client module and make sure you have the RethinkDB server ready and running, listening to the default port.
  3. Make sure you have done npm install rethinkdb before running the following code:
          var rethinkdb = require('rethinkdb'); 
          var connection = null; 
          rethinkdb.connect({host : 'localhost', port :
                             28015},function(err,conn) { 
          if(err) {  
          throw new Error('Connection error');  
           } else { 
          connection = conn; 
           } 
           }); 
    

The preceding simple code snippet written in Node.js is importing the rethinkdb module and connecting to the RethinkDB server on the default port. It returns the callback function with error and the connection variable, and upon getting the connection object, we are good to go!

By default, RethinkDB creates and connects to the default database named test. We can perform various operations on it such as creating a table or performing CRUD operations.

Let's begin with creating a simple table to store blog posts as follows:

rethinkdb.db('test').tableCreate('authors') 
.run(connection, function(err, result) { 
    if (err) throw err; 
console.log(JSON.stringify(result)); 

Upon running the code, you should get the following on your console:

{ 
   "config_changes":[ 
      { 
         "new_val":{ 
            "db":"test", 
            "durability":"hard", 
            "id":"a168e362-b7e7-4260-8b93-37ee43430bac", 
            "indexes":[ 
             ], 
            "name":"authors", 
            "primary_key":"id", 
            "shards":[ 
               { 
                  "nonvoting_replicas":[ 
                   ], 
                  "primary_replica":"Shahids_MacBook_Air_local_pnj", 
                  "replicas":[ 
                     "Shahids_MacBook_Air_local_pnj" 
                  ] 
               } 
            ], 
            "write_acks":"majority" 
         }, 
         "old_val":null 
      } 
   ], 
   "tables_created":1 
} 

In our code, we need to check out the tables_created key in order to determine whether the table was created or not.

We can check whether the table was created or not in the administrative web console too. Point your browser to http://localhost:8080 and go to the DATABASE section from the menu. You should be able to see something like the following:

Embedding ReQL in a programming language

In order to run the code in Node.js, since you get the connection object in callback and it's asynchronous, you need to manage the flow of the code. For now, you can just paste the code to create a table inside the closure callback of the connection and it should work fine. But when writing code for production, make sure you handle the callback flow well and do not end up being in a callback hell situation.

One of the best ways to manage it and which I use very frequently while coding Node.js programs is by using the async node module. It has a rich set of functions to properly manage and design your code. Of course, there will be no chance of callback hell and you can by far manage not to go for more than four levels of nesting (three is ideal but very tricky to reach).

We have our database up and running and we have created the table using our code. The next is to performing the very famous CRUD (Create, read, update and delete) operation on the table. This will not only cover some important functions of the RethinkDB query language but also will give a quick kick to perform basic operations, which you have probably been doing in other NoSQL and SQL databases.

Performing CRUD operations using RethinkDB and Node

Let's begin by creating a fresh new table named users and perform CRUD operations using ReQL queries as follows:

varrethinkdb = require(''rethinkdb''rethinkdb'); 
var connection = null; 
rethinkdb.connect({host : ''localhost''localhost', port : 28015},function(err,conn) { 
if(err) {  
throw new Error(''Connection error''Connection error');  
 } else { 
connection = conn; 
 } 
}); 

We will use the default database to perform this operation. After getting the connection, we will create a table using the following code:

rethinkdb.db('test','test').tableCreate('authors','authors').run(connection,  
function(err, result) {  
    if (err) throw err;  
console.log(JSON.stringify(result)); }); 
});  

Make sure that this piece of code is placed correctly within the else section of the connection code. Since we have created the table, we can perform the operation on it.

Creating new records

ReQL provides the insert() function to create new documents in the table. Here is the code to do so.:

 rethinkdb.db('test','test').table('users','users').insert({
 userId : "shahid",
 password : "password123",
 createdDate : new Date()
 }).run(connection,function(err,response) { 
 if(err) {
 throw new Error(err);
 }
 console.log(response); 
 }); 

Upon running the code, RethinkDB returns the following.:

{ 
 deleted: 0, 
 errors: 0, 
 generated_keys: [ ''e54671a0'e54671a0-bdcc-44ab-99f3-90a44f0291f8'' ], 
 inserted: 1, 
 replaced: 0, 
 skipped: 0, 
 unchanged: 0 
 } 

Providing database details is optional in the query. The key to look for in the code is inserted, which determines whether the document was inserted or not. Since we are not providing the primary key from our side, RethinkDB generates it automatically and you can find that in the generated_keys.

You can add much more complex data in the RethinkDB than you can do in any other NoSQL database. You can also store nested objects, arrays, binary objects, and so on. We will look over binary objects in the upcoming section.

Reading the document data

You can read the documents from the table using the get() or getAll() ReQL method. Here is a query to retrieve all the documents present in the table:

 rethinkdb.table('users','users').run(connection,function(err,cursor) { 
 if(err) { 
 throw new Error(err); 
 } 
 cursor.toArray(function(err,result) { 
 console.log(result); 
 }); 
 });

The preceding code performs the read operation in the table and returns you cursor. Cursor provides a batch of data in sequence instead of whole data at once. We use the toArray() function to read the information in the batch. It should print the following on the console:

[ {  
createdDate: 2016-06-09T08:58:15.324Z, 
id: ''e54671a0'e54671a0-bdcc-44ab-99f3-90a44f0291f8'', 
password: ''password123'''password123', 
userId: ''shahid'''shahid'  
} ] 

You can also read specific data based on the filter. Let's try to read the data with the uniquely generated ID the using the get() method as follows:

rethinkdb.table('users').get('e54671a0-bdcc-44ab-99f3-90a44f0291f8') 
 .run(connection,function(err,data) { 
if(err) { 
throw new Error(err); 
    } 
console.log(data); 
  }); 

It will return a single document from the table without the cursor. You can get the response in the callback variable.

As you may have noticed, we are directly accessing the table in the query without passing the database name because the connection variable contains the database information.

Updating the document

You can perform the update operation on the document using the update() function which accepts the object as an argument. You can at least update one key or the whole document (all keys) after fetching the document. Here is the code snippet to do so:

rethinkdb.table('users') 
    .get('e54671a0-bdcc-44ab-99f3-90a44f0291f8') 
    .update({userId : 'shahidShaikh'}) 
    .run(connection,function(err,response) { 
if(err) { 
throw new Error(err); 
      } 
console.log(response); 
   }); 

In order to update the document, we first fetch it using the get() method and then running the update() function. We are just updating the userId key here but you can pass other keys as well.

It will return the following on the console:

{  
deleted: 0, 
errors: 0, 
inserted: 0, 
replaced: 1, 
skipped: 0, 
unchanged: 0  
} 

The key to look for in the code is replaced, which, if it returns 1, means the update operation is successfully committed; otherwise, in the case of any other value, there is an error.

You can also use replace() ReQL method to replace the entire document with a new document. This method generates a new document and do not preserve the same ID as the update() method does.

You can validate the data by either running the get() method again or running the following code in the web administrative console:

r.db('test').table('users').get('e54671a0-bdcc-44ab-99f3-90a44f0291f8') 

Updating the document

Deleting the document

We can use the delete() ReQL commands to perform a deletion. Again we need to fetch the record first and then perform the delete operation. You can perform a delete all operation as well by first fetching all documents. Here is the code to do so:

rethinkdb.table('users') 
    .get('e54671a0-bdcc-44ab-99f3-90a44f0291f8') 
    .delete() 
    .run(connection,function(err,response) { 
if(err) { 
throw new Error(err); 
      } 
console.log(response); 
    }); 

This should print the following on the terminal:

{  
deleted: 1, 
errors: 0, 
inserted: 0, 
replaced: 0, 
skipped: 0, 
unchanged: 0  
} 

You can check out the deleted key to know the status of the delete operation. If you want to delete all the documents from the database, you can do so by selecting all documents first and appending the delete() operation as follows:

rethinkdb.table('users') 
    .delete() 
    .run(connection,function(err,response) { 
if(err) { 
throw new Error(err); 
      } 
console.log(response); 
    }); 
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.147.59.198