After introduction to node.js it’s time to go with more advanced and practical information. Today we play with communication between node.js and MySQL databases, and also we mention of MongoDB.
Node.js and MySQL
If we code using e.g. PHP, we should have LAMP installed in our system, so then we have also MySQL. Additionally we need only node.js and MySQL module:
$ npm install mysql
Configuration
For convenience, let’s create config.js configuration file:
var config = {}; config.db = {}; config.db.type = 'mysql'; config.db.charset = 'utf8'; config.db.username = 'user'; config.db.password = 'pass'; config.db.host = 'localhost'; config.db.dbname = 'node_tests'; // DB name config.db.users_tbl = 'users'; // table name // config.db.another_tbl = 'next_table'; // … // export module.exports = config;
We created a simple object that stores configuration. It’s important to “export” this object:
module.exports = config;
Now we can write our test script to make MySQL connection.
Example:
var mysql = require('mysql'); var config = require('./config.js'); var db_access = { host : config.db.host, user : config.db.username, password : config.db.password, database : config.db.dbname }; var tbl = config.db.users_tbl; var conn = mysql.createConnection(db_access); conn.connect(); var queryString = 'SELECT * FROM ' + tbl; conn.query(queryString, function (err, rows, fields) { if (err) { throw err; } for (var i in rows) { console.log('User names: ', rows[i].name); } }); conn.end();
The code is neat, and his job is to retrieve and display users from our test database (for test purpose we need at least ID and firstname fields in DB table).
We start by adding necessary modules — mysql and our configuration. Then, create an access to the database, required by createConnection() function.
That object must contain following fields:
host, user, password, database
These data were obtained from our configuration file.
Next step it to establish connection and execute the query — conn.query(). At the end, we close connection.
Handling events
It’s a way to handle individual cases, such as received data ready for processing, an error occurred, etc.
var query = connection.query(queryString); query.on('result', function(row) { console.log(row.firstname); /* connection.pause(); // do some more processing on the row … console.log(row); connection.resume(); */ }); query.on('error', function(err) { throw err; }); connection.on('close', function(err) { if (err) { // unexpected closing of connection - reconnect back connection = mysql.createConnection(connection.config); } else { console.log('Connection closed'); } }); connection.end();
Node.js — creating DB and tables
There is no problem with performing other queries, such as creating databases and tables, as illustrated by the following examples:
connection.query('CREATE DATABASE foobar'); connection.changeUser({database: 'foobar'}); // or just connection.query('USE foobar') // table structure connection.query('CREATE TABLE foobar.mytable(' + 'id INT NOT NULL AUTO_INCREMENT, ' + 'author VARCHAR( 128 ) NOT NULL, ' + 'quote TEXT NOT NULL, PRIMARY KEY ( id )' + ')');
SQL injection, security, stability
Back-end developers should know well such issues.
Although we can use the connection.escape function:
connection.connect(); var key = 'something…'; var queryString = 'SELECT * FROM posts WHERE key = ' + connection.escape(key); connection.query(queryString, function(err, rows, fields) { … });
But suppose we implement “Add a comment” feature, or something similar, where we use text gathered from the user, as a part of SQL Insert query.
We have to handle data, as it’s not only about security, but also about stability of our application.
For example apostrophes in text may cause syntactic error of the query. Then our entire node.js script can be interrupted.
So we can easy write our own functions, e.g. sanitize(), or well-known from PHP, addslashes() function (php.js).
Sample implementation:
// mytools.js var mytools = { sanitize: function (html) { return String(html) .replace(/&(?!\w+;)/g, '&') .replace(/</g, '<') .replace(/>/g, '>') .replace(/"/g, '"'); }, addslashes: function (str) { return (str + '') .replace(/[\"']/g, '\$&') .replace(/\u0000/g, 'After introduction to node.js it’s time to go with more advanced and practical information. Today we play with communication between node.js and MySQL databases, and also we mention of MongoDB.
Node.js and MySQL
If we code using e.g. PHP, we should have LAMP installed in our system, so then we have also MySQL. Additionally we need only node.js and MySQL module:
$ npm install mysql
Configuration
For convenience, let’s create config.js configuration file:
var config = {}; config.db = {}; config.db.type = 'mysql'; config.db.charset = 'utf8'; config.db.username = 'user'; config.db.password = 'pass'; config.db.host = 'localhost'; config.db.dbname = 'node_tests'; // DB name config.db.users_tbl = 'users'; // table name // config.db.another_tbl = 'next_table'; // … // export module.exports = config;We created a simple object that stores configuration. It’s important to “export” this object:
module.exports = config;
Now we can write our test script to make MySQL connection.
Example:
var mysql = require('mysql'); var config = require('./config.js'); var db_access = { host : config.db.host, user : config.db.username, password : config.db.password, database : config.db.dbname }; var tbl = config.db.users_tbl; var conn = mysql.createConnection(db_access); conn.connect(); var queryString = 'SELECT * FROM ' + tbl; conn.query(queryString, function (err, rows, fields) { if (err) { throw err; } for (var i in rows) { console.log('User names: ', rows[i].name); } }); conn.end();The code is neat, and his job is to retrieve and display users from our test database (for test purpose we need at least ID and firstname fields in DB table).
We start by adding necessary modules — mysql and our configuration. Then, create an access to the database, required by createConnection() function.
That object must contain following fields:
host, user, password, database
These data were obtained from our configuration file.
Next step it to establish connection and execute the query — conn.query(). At the end, we close connection.
Handling events
It’s a way to handle individual cases, such as received data ready for processing, an error occurred, etc.
var query = connection.query(queryString); query.on('result', function(row) { console.log(row.firstname); /* connection.pause(); // do some more processing on the row … console.log(row); connection.resume(); */ }); query.on('error', function(err) { throw err; }); connection.on('close', function(err) { if (err) { // unexpected closing of connection - reconnect back connection = mysql.createConnection(connection.config); } else { console.log('Connection closed'); } }); connection.end();Node.js — creating DB and tables
There is no problem with performing other queries, such as creating databases and tables, as illustrated by the following examples:
connection.query('CREATE DATABASE foobar'); connection.changeUser({database: 'foobar'}); // or just connection.query('USE foobar') // table structure connection.query('CREATE TABLE foobar.mytable(' + 'id INT NOT NULL AUTO_INCREMENT, ' + 'author VARCHAR( 128 ) NOT NULL, ' + 'quote TEXT NOT NULL, PRIMARY KEY ( id )' + ')');SQL injection, security, stability
Back-end developers should know well such issues.
Although we can use the connection.escape function:
connection.connect(); var key = 'something…'; var queryString = 'SELECT * FROM posts WHERE key = ' + connection.escape(key); connection.query(queryString, function(err, rows, fields) { … });But suppose we implement “Add a comment” feature, or something similar, where we use text gathered from the user, as a part of SQL Insert query.
We have to handle data, as it’s not only about security, but also about stability of our application.
For example apostrophes in text may cause syntactic error of the query. Then our entire node.js script can be interrupted.
So we can easy write our own functions, e.g. sanitize(), or well-known from PHP, addslashes() function (php.js).
Sample implementation:
// mytools.js var mytools = { sanitize: function (html) { return String(html) .replace(/&(?!\w+;)/g, '&') .replace(/</g, '<') .replace(/>/g, '>') .replace(/"/g, '"'); }, addslashes: function (str) { return (str + '') .replace(/[\"']/g, '\$&') .replace(/\u0000/g, '\0'); } }; module.exports = mytools;Usage
var tools = require('./mytools.js'); var comment = tools.sanitize(res_data.comment); // comment = tools.addslashes(comment);In this way, we can safely use the variable in our query. We will avoid both using dangerous elements (e.g. JS scripts in the content), as well as issues with executing queries (apostrophes in text).
Query example — node.js and MySQL — Insert:
function insertCommentData(socket, our_data) { var connection = mysql.createConnection(db_access); connection.connect(); var clean = tools.addslashes(socket.content); var q = "INSERT INTO " + comments_tbl; q += " (user_id, content, created_at)"; q += " VALUES (" + socket.user_id + ", " + clean + ", NOW() )"; // console.log(q); connection.query(q, function (qe, qr) { if (qe) { console.log(qe); } // do something with result … connection.end(); }); }When querying, we can perform some operations on the result, and e.g. close the connection, if won’t be necessary anymore.
The qe and qr variables are respectively: query errors (if any) and the query results.
Very useful information from the result can be the ID of last inserted record.
Example — last insert ID:
… connection.query(q, function (qe, qr) { if (qe) { console.log(qe); } // add new information to the object our_data.comment_id = qr.insertId; // send this object to all sockets io.sockets.emit("e_new_comment", { message: our_data }); connection.end(); });Examples assume data transfer through the socket. About socket.io we will write more in the next article.
SELECT COUNT
Now we show how to execute and get the result of SELECT COUNT query.
For example we may want to execute INSERT query (add new data), or UPDATE, depending on whether a record is already in the database or not:
function setStatus(user_id, status) { var connection = mysql.createConnection(db_access); connection.connect(); var q1 = "SELECT COUNT(1) AS cnt FROM " + user_status_tbl + " WHERE user_id = '" + user_id + "'"; connection.query(q1, function (err, rows, fields) { if (err) { console.log(err); } if ((rows[0].cnt) > 0) { // update var q2 = "UPDATE " + user_status_tbl + " SET status = " + status + ", updated_at = NOW() "; q2 += "WHERE user_id = '" + user_id + "' "; connection.query(q2, function (qe, qr) { if (qe) { console.log(qe); } console.log('Updated #' + user_id); connection.end(); }); } else { // add var q2 = "INSERT INTO " + user_status_tbl + " (user_id, updated_at, status) "; q2 += "VALUES (" + user_id + ", NOW(), " + status + ")"; connection.query(q2, function (qe, qr) { if (qe) { console.log(qe); } console.log('Inserted #' + user_id); connection.end(); }); } }); }We added alias “cnt” for out result, so we refer as following: rows[0].cnt
With these fundamentals, we are actually ready to work effectively with node.js and MySQL.
Now let’s take a look at MongoDB — another database, very popular in case of node.js.
Node.js and MongoDB
Mongo is open, non-relational database management system, characterized by high scalability.
The data are stored as documents in the JSON format, which allows applications to process the data in more natural way, with maintaining the ability to create a hierarchy and indexing. It is a very efficient system.
Preparation
Install MongoDB for our system.
E.g. in Windows:
$ cd C:\Program Files\MongoDB 2.6 Standard\bin
$ md \data\md
$ mongod
New DB:
$ mongod –dbpath C:\Projects\node\catalog1\data
Open the next console and connect to the DB:
$ cd C:\Program Files\MongoDB 2.6 Standard\bin
$ mongo
In mongo console write:
$ use catalog1
We choose the database. We can now insert test data in console:
db.usercollection.insert({ "username" : "testuser1", "email" : "testuser1@testdomain.com" }) // …Getting data (the pretty() function adds linebreaks):
$ db.usercollection.find().pretty()
To save data permanently, use save():
db.usercollection.save({ "username" : "testuser1", "email" : "testuser1@testdomain.com" }) // …Remove all data:
db.dropDatabase();To work with MongoDB in node.js, we will need modules mongodb, and for example monk:
var mongo = require('mongodb'); var monk = require('monk'); var db = monk('localhost:27017/catalog1'); …In one of the next tutorials we will write about express.js, and then we also will work more with MongoDB in practice.
Node.js and MySQL — summary
We have tried to present the key information you need to work with MySQL in node.js. Also mentioned about MongoDB. We’re working on the next articles and tutorials about great node.js technology (and related solutions).
Thank you!
[…] presenting basics of node.js and how to work with databases, it’s time to reach for even more interesting […]
[…] Then we call the insertComment() function, which saved the data in DB. […]