Rethink Database for Creating a Realtime Web Application with Node JS
Wall Script
Wall Script
Monday, June 06, 2016

Rethink Database for Creating a Realtime Web Application with Node JS

Earlier in realtime, any request for data from the server makes the app slow, unscalable and cumbersome to maintain. RethinkDB mainly focus on this drawback and makes building realtime apps easier. RethinkDB is the first open-source, scalable JSON database built for realtime web. The developer can tell RethinkDB to continuously push updated query results to application in realtime; this reduces the server load and also the time and effort necessary to build scalable realtime apps. Here there is complete steps for installing RethinkDB. This post also explains you to create a reat-time web application using RethinkDB and Node.js

RethinkDB Nodejs tutorial


Download Script

Developer
 Shashank Tiwari
Shashank Tiwari
Designer & Developer
Mumbai, INDIA
codershood.info



What is RethinkDB:
RethingDB is NoSQL, open source, distributed document-oriented database specially built for the real-time web. It uses ReQL query language.
Read more about ReQL query language: Introduction-to-ReQL.

Why RethinkDB
We are entering into an era of the real-time web application or I should say we have already entered. With the advent of Websockets, It is possible to create a real-time application in no time.
Earlier, we used to pull data from the server in real time and show it to the user with a restriction that server load should not increase. Well here comes the RethinkDB, which reduces this step.
We can tell RethinkDB to pull data from Table whenever any new changes occur in other words, we can subscribe for changes in any table. This feature reduces a lot of server load and developer need not put a lot of effort for pulling data from the server.

Let's start off by installing rethinkDB

Installing RethinkDB
RethinkDB provides drivers for all major OS, visit https://rethinkdb.com/docs/install/ link to find out various official packages available for different.

Installing in Mac (OS X):
Go to this link and download Mac installer or you can install RethinkDB using Using Homebrew.
If you have brew installed then run the below command.

brew update && brew install rethinkdb

Installing in Ubuntu
To install RethinkDB in ubuntu run the below command in cmd one by one.
source /etc/lsb-release && echo "deb http://download.rethinkdb.com/apt $DISTRIB_CODENAME main" | sudo tee /etc/apt/sources.list.d/rethinkdb.list

wget -qO- https://download.rethinkdb.com/apt/pubkey.gpg | sudo apt-key add -

sudo apt-get update
sudo apt-get install rethinkdb

and you are done.

Installing in Windows
Go to this link and download windows installer. Now unzip the downloaded file and paste in your choice of the directory. Run the file and follow the screen instructions to complete the installation.

That’s it, simplest installation of them all isn't it. :D

Starting RethinkDB server
Now to start the RethinkDB server, Open CMD type below command,
rethinkdb
After executing the above command, If you see the below screen with some message than congratulations, you have successfully installed RethinkDB server.


Starting RethinkDB's Administrative panel
RethinkDb has it's own administrative panel just like PhpMyAdmin (where we manage our MySql database table). In RethinkDB's administrative panel we can manage our clusters and we can check our logs. To open administrative panel type below command in CMD.
rethinkdb --bind all
To access the web management console, open http://localhost:8080 in your browser. On this link, you should see the below Image,


Creating real-time web application
Assuming you have installed RethinkDB in your machine. Now let's create a basic application using Nodejs and RethinkDB, In this application we will perform CRUD operation with a real-time update as well as we will see how to filter records.
To start a new project, Type below command,
npm init
Run below command to install RethinkDB client driver.
npm install --save rethinkdb
Before we start let's take a look at our folder structure for this application. In the middleware folder,where we have our config files.


+--- middleware
| +-- config.js
| +-- db.js
| +---routes
|
+--- node_modules
| +---body-parser
| +---ejs
| +---express
| +---socket.io
| +---rethinkdb
|
+--- views
| css
| +-- bootstrap.min.css
| +-- style.css
| js
| +-- angular.min.js
| +-- script.js (Script to handle Client )
| +-- home.html
|
+---server.js
+---package.json

Here is our package.json file,
package.json
{
"name": "RethinkDB-Nodejs-tutorial",
"version": "0.0.1",
"description": "RethinkDB-Nodejs-tutorial",
"author": "Shashank Tiwari",
"license": "MIT",
"dependencies": {
"express": "^4.13.4",
"ejs": "^2.4.1",
"body-parser": "^1.15.0",
"socket.io": "^1.4.5",
"rethinkdb": "^2.3.1"
}
}


Now run npm install to install all dependencies. Or you can do it manually in a geek way.
Creating Nodejs server:
1. Create a file named as server.js to handle RethinkDB operation and to deliver static files to the client user.
2. As you can see in the below code, we are requiring node_modules in first three lines. After that, we are again requiring two files named as config.js and routes.js from middleware folder.
3. config.js: This file used to tell express where to find all static files.
4. routes.js: This file is used to handle all routes.
server.js:
/*requiring node modules starts */
var app = require("express")();
var http = require('http').Server(app);
var io = require("socket.io")(http);

/*requiring node modules ends */
require('./middleware/config.js')(app);
require('./middleware/routes.js')(app,io);

/*Running our application*/
http.listen(81,function(){
console.log("Listening on http://127.0.0.1:81");
});

3. Create a file db.js inside middleware folder. This file takes care of database connection.
db.js:
"use strict";
/*requiring rethinkdb node modules */
const rethinkdb = require('rethinkdb');
module.exports.onConnect = function(callback){
rethinkdb.connect( {host: 'localhost', port: 28015}, function(err, connection) {
if (err) throw err;
callback(rethinkdb,connection);
});
};
4. Now tell the express where to find static files by creating config.js files in middleware folder. Note that we have already required this in file in server.js file.

config.js:
var express = require("express");
var path= require('path');
var method=config.prototype;

function config(app){
// Setting .html as the default template extension
app.set('view engine', 'html');

// Initializing the ejs template engine
app.engine('html', require('ejs').renderFile);

// Telling express where it can find the templates
app.set('views', (__dirname + '/../views'));

//Files
app.use(express.static(path.join('views')));
}
method.get_config=function(){
return this;
}
module.exports = config;

5. Now create a file named as routes.js in middleware folder to handle all the routes. In the below we have 4 routes listed below,
1 / : Which needs no introduction I believe :D.
2. /addPlayer : In this route we will be inserting records.
3. /filterPlayers : In this route we will fetch records.
4. /deletePlayer : This route is ued to delete records.
routes.js:

"use strict";
const db= require("./db");
const bodyParser = require('body-parser');

/*---------------------------------------------------------------------------------
creating Table
---------------------------------------------------------------------------------*/
var createTable=function (callback){
db.onConnect(function(rethinkdb,connection){
rethinkdb.db('test').tableList().contains('players').run(connection, function(err, result){
if(err){
console.log('Error :'+ err );
}else{
if(!result){
rethinkdb.db('test').tableCreate('players').run(connection, function(err, result) {
if(err){
throw err;
}else{
callback("Table Created");
}
});
}
}
});
});
}
createTable(function(data){
console.log(data);
});

var method=routes.prototype;
function routes(app,io){

app.use(bodyParser.json());

app.get('/',function(req, res){
res.render('home');
});

app.post('/addPlayer', function(req, res){
/*---------------------------------------------------------------------------------
Inserting records
---------------------------------------------------------------------------------*/
db.onConnect(function(rethinkdb,connection){
rethinkdb.table('players').insert([
{
player_name: req.body.playerName,
sport_name: req.body.sportName,
country_name: req.body.countryName
}
]).run(connection, function(err, result) {
if (err) {
throw err
}else{
res.write(JSON.stringify({
process:"success"
}));
res.end();
}
});
});
});

app.post('/filterPlayers',function(req,res){

/*---------------------------------------------------------------------------------
fetching records
---------------------------------------------------------------------------------*/

var filter={};
if (typeof req.body.filterPlayerName != "undefined" && req.body.filterPlayerName != "") {
filter.player_name=req.body.filterPlayerName;
}
if(typeof req.body.filtersportName != "undefined" && req.body.filtersportName != ""){
filter.sport_name=req.body.filtersportName;
}
if(typeof req.body.filtercountryName != "undefined" && req.body.filtercountryName != ""){
filter.country_name=req.body.filtercountryName;
}

db.onConnect(function(rethinkdb,connection){
rethinkdb.table('players').filter(filter).run(connection, function(err, cursor) {
if (err) throw err;
cursor.toArray(function(err, result) {
if (err) {
throw err
}else{
res.write(JSON.stringify(result));
res.end();
}
});
});
});
});

app.post('/deletePlayer', function(req, res){

/*---------------------------------------------------------------------------------
deleting records
---------------------------------------------------------------------------------*/
db.onConnect(function(rethinkdb,connection){
rethinkdb.table("players").get(req.body.id).delete().run(connection, function(err, cursor) {
if (err){
throw err;
}else{
console.log("Deleted");
}
});
});

});
io.on('connection',function(socket){
db.onConnect(function(rethinkdb,connection){

/*---------------------------------------------------------------------------------
fetching records when client is connceted to server
---------------------------------------------------------------------------------*/
rethinkdb.table('players').run(connection, function(err, cursor) {
if (err) throw err;
cursor.toArray(function(err, result) {
if (err) throw err;
socket.emit('getAllPlayers',result);
});
});

/*---------------------------------------------------------------------------------
subscribing to the table for realtime update
---------------------------------------------------------------------------------*/
rethinkdb.table("players").changes().run(connection, function(err, cursor) {
if (err) {
// Handle error
return
}
cursor.on("error", function(error) {
throw error;
})
cursor.on("data", function(player) {
socket.emit("getMsg", player);
})
});
});
});

}

method.getroutes=function(){
return this;
}

module.exports = routes;

Till now we have created our files required for server now let's create files for Front End.

Creating front-end
In front-end, we will use AnguarJs for JS and bootstrap for CSS. We will create 2 folders in the views folder named as JS and CSS.
Also, Read Learn AnguarJs tutorial.
Create home.html in views folder and write the below code.
home.html
<html ng-app="home">
<head>
<title>RethinkDB Nodejs tutorial</title>
<link rel="stylesheet" href="css/bootstrap.min.css">
<link rel="stylesheet" href="css/font-awesome.min.css">
<link rel="stylesheet" href="css/style.css">
</head>
<body ng-controller="home">
<div class="body container">
<div class="row playerRow">
<div class="col-md-4">
<div class="row insertConatiner">
<h4>Add Player</h4>
<input type="text" ng-model="playerName" class="form-control inputBox playerName" id="playerName" placeholder="Enter the Plyer name">
<input type="text" ng-model="sportName" class="form-control inputBox sportName" id="sportName" placeholder="Enter the Sport name">
<input type="text" ng-model="countryName" class="form-control inputBox countryName" id="countryName" placeholder="Enter the Country name">
<button class="btn btn-primary buttonPlayer addPlayer" ng-click="addPlayer()">Add Player </button>
</div>
<div class="row filterConatiner">
<h4>Filter Record</h4>
<input type="text" ng-model="filterPlayerName" class="form-control inputBox filterPlayerName" id="filterPlayerName" placeholder="Enter the Plyer name">
<input type="text" ng-model="filtersportName" class="form-control inputBox filtersportName" id="filtersportName" placeholder="Enter the Sport name">
<input type="text" ng-model="filtercountryName" class="form-control inputBox filtercountryName" id="filtercountryName" placeholder="Enter the Country name">
<button class="btn btn-primary buttonPlayer filterPlayer" ng-click="filterPlayer()"> Filter Player </button>
</div>
</div>
<div class="col-md-8 showPlayerList">
<h4>List of Players</h4>
<div class="list">
<div class="singlePlayer" ng-repeat="(key,player) in players" id="player_{{player.id}}">
<h5 ng-click="deletePlayer(player.id,key)">
<span class="glyphicon glyphicon-remove removeRecord"></span>
</h5>
<h5>Player name : {{ player.player_name }}</h5>
<h6>Sport : {{ player.sport_name }}</h6>
<h6>Country : {{ player.country_name }}</h6>
</div>
<div ng-show="players.length == 0" class="alert alert-danger">
No Record Found.
</div>
</div></div></div>
</div>
<script type="text/javascript" src = "js/angular.min.js"></script>
<script type="text/javascript" src="/socket.io/socket.io.js"></script>
<script type="text/javascript" src ="js/script.js"></script>
</body>
</html>

Let's create an AngularJs script for sending a request to the server. Create a script.js file in the JS folder and write below code.
In below script, we have integrated socket.io with AngularJs by using a Factory method. Read more about Writing an AngularJS App with Socket.IO. Just below that we have created a service to run Ajax.
script.js:

"use strict";

var app = angular.module('home',[]);
/*---------------------------------------------------------------------------------
Making factory method for socket
---------------------------------------------------------------------------------*/
app.factory('socket', function ($rootScope) {
var socket = io.connect();
return {
on: function (eventName, callback) {
socket.on(eventName, function () {
var args = arguments;
$rootScope.$apply(function () {
callback.apply(socket, args);
});
});
},
emit: function (eventName, data, callback) {
socket.emit(eventName, data, function () {
var args = arguments;
$rootScope.$apply(function () {
if (callback) {
callback.apply(socket, args);
}
});
})
}
};
});

/*---------------------------------------------------------------------------------
Making service to run ajax
---------------------------------------------------------------------------------*/
app.service('runajax', ['$http', function ($http) {
this.runajax_function = function(request,callback){
var url=request.url;
var data_server=request.data_server;
$http.post(url,data_server).success(function(data, status, headers, config) {
callback(data);
})
.error(function(){
callback("data");
});
}
}]);

app.controller('home', function ($scope,socket,runajax) {

$scope.players=[];

/*---------------------------------------------------------------------------------
Call to add Player
---------------------------------------------------------------------------------*/

$scope.addPlayer = function() {
if (typeof $scope.playerName == "undefined" || $scope.playerName == "" ) {

alert(`Enter player Name`);

}else if(typeof $scope.sportName == "undefined" || $scope.sportName == "" ){

alert(`Enter Sport Name`);

}else if(typeof $scope.countryName == "undefined" || $scope.countryName == "" ){

alert(`Enter Country Name`);

}else{
var data={
url:'/addPlayer',
data_server:{
playerName:$scope.playerName,
sportName:$scope.sportName,
countryName:$scope.countryName
}
}
runajax.runajax_function(data,function(userdata){
$scope.playerName="";
$scope.sportName="";
$scope.countryName="";
});
}
};

/*---------------------------------------------------------------------------------
Call to Filter
---------------------------------------------------------------------------------*/
$scope.filterPlayer = function() {
var data={
url:'/filterPlayers',
data_server:{
filterPlayerName:$scope.filterPlayerName,
filtersportName:$scope.filtersportName,
filtercountryName:$scope.filtercountryName
}
}
runajax.runajax_function(data,function(data){
$scope.players=data;
});
};

/*---------------------------------------------------------------------------------
Call to delete
---------------------------------------------------------------------------------*/
$scope.deletePlayer = function(id) {
var data={
url:'/deletePlayer',
data_server:{
id:id
}
}
runajax.runajax_function(data,function(data){
});
};


/*---------------------------------------------------------------------------------
Socket on event starts
---------------------------------------------------------------------------------*/
socket.on('getMsg',function(data){
if(data.new_val != null){
$scope.players.push(data.new_val);
}else{
document.getElementById('player_'+data.old_val.id).style.display = "none";
alert(`Record Deleted`);
}
});

socket.on('getAllPlayers',function(data){
$scope.players=data;
});
/*---------------------------------------------------------------------------------
Socket on event Ends
---------------------------------------------------------------------------------*/
});

We have completed the front-end part as well as created Nodejs server. Now open your CMD Run your application by node server.js. Open http://127.0.0.1:81 in browser to see the output.
web notification

12 comments:

  1. Why do you think Rethink is better than MongoDB?

    ReplyDelete
    Replies
    1. RethinkDB’s realtime architecture can be compared to MongoDB’s oplog, but offers a much higher level of abstraction. RethinkDB’s feeds integrate seamlessly with the query computation engine, and allow you to subscribe to changes on query results, not just raw replication data. This architecture dramatically reduces the time and effort necessary to build scalable realtime apps.

      Read more :https://rethinkdb.com/faq/

      Delete
  2. Hi sir, just want to know that how much you earned from this blog from starting date till today using adsense or affiliate on your blog

    Thanks....

    ReplyDelete
  3. This is great tutorial, it makes all simple, i love you 9lessons...

    ReplyDelete
  4. Well, look very interesting. Nice tutorial !

    ReplyDelete
  5. Very Nice Source an Tutorial ..Thanks Sri !!

    ReplyDelete
  6. Thank You for sharing your article. This is very informative article to web application with node JS.
    Keep it up.

    ReplyDelete
  7. Hi Srinivas,
    I am trying to update realtime in rethinkdb using change feed in node js event call which is working but when row is deleted from rethinkdb then node js program shuts down ie coming to the terminal. What I want ,if data deleted from rethinkdb ,node js event call will continue ,not to come out of the program . code is given below
    setTimeout(function() {
    r.db('db name').table("table name").filter({"userid": temp.new_val.userid})
    .update({"status": "true"}).run(connection,function(err,result){
    if(err) throw err;
    console.log('updated');

    });
    },1000);

    ReplyDelete
  8. How do I pass a extra parameter in socket.on from client side and read it on server side?

    ReplyDelete
  9. How do I pass extra parameters in socket.on from client side and read it on server side?

    ReplyDelete

mailxengine Youtueb channel
Make in India
X