Why?
After looking at Google Analytics stats I’ve realized that there is a demand for short Node.js tutorial and quick start guides. This is an introduction to probably the most popular (as of April 2013) Node.js framework Express.js.
mongoui
This app is a start of mongoui project. A phpMyAdmin counterpart for MongoDB written in Node.js. The goal is to provide a module with a nice web admin user interface. It will be something like Parse.com, Firebase.com, MongoHQ or MongoLab has but without trying it to any particular service. Why do we have to type db.users.findOne({'_id':ObjectId('...')})
any time we want to look up the user information? The alternative of MongoHub mac app is nice (and free) but clunky to use and not web based.
REST API app with Express.js and Monk
Ruby enthusiasts like to compare Express to Sinatra framework. It’s similarly flexible in the way how developers can build there apps. Application routes are set up in a similar manner, i.e., app.get('/products/:id', showProduct);
. Currently Express.js is at version number 3.1. In addition to Express we’ll use Monk module.
We’ll use Node Package Manager which is usually come with a Node.js installation. If you don’t have it already you can get it at npmjs.org.
Create a new folder and NPM configuration file, package.json, in it with the following content:
{
"name": "mongoui",
"version": "0.0.1",
"engines": {
"node": ">= v0.6"
},
"dependencies": {
"mongodb":"1.2.14",
"monk": "0.7.1",
"express": "3.1.0"
}
}
Now run npm install
to download and install modules into node_module folder. If everything went okay you’ll see bunch of folders in node_modules folders. All the code for our application will be in one file, index.js, to keep it simple stupid:
var mongo = require('mongodb');
var express = require('express');
var monk = require('monk');
var db = monk('localhost:27017/test');
var app = new express();
app.use(express.static(__dirname + '/public'));
app.get('/',function(req,res){
db.driver.admin.listDatabases(function(e,dbs){
res.json(dbs);
});
});
app.get('/collections',function(req,res){
db.driver.collectionNames(function(e,names){
res.json(names);
})
});
app.get('/collections/:name',function(req,res){
var collection = db.get(req.params.name);
collection.find({},{limit:20},function(e,docs){
res.json(docs);
})
});
app.listen(3000)
Let break down the code piece by piece. Module declaration:
var mongo = require('mongodb');
var express = require('express');
var monk = require('monk');
Database and Express application instantiation:
var db = monk('localhost:27017/test');
var app = new express();
Tell Express application to load and server static files (if there any) from public folder:
app.use(express.static(__dirname + '/public'));
Home page, a.k.a. root route, set up:
app.get('/',function(req,res){
db.driver.admin.listDatabases(function(e,dbs){
res.json(dbs);
});
});
get()
function just takes two parameters: string and function. The string can have slashes and colons, for example product/:id
. The function must have two parapemets request and response. Request has all the information like query string parameters, session, headers and response is an object to with we output the results. In this case we do it by calling res.json()
function. db.driver.admin.listDatabases()
as you might guess give us a list of databases in async manner.
Two other routes are set up in a similar manner with get()
function:
app.get('/collections',function(req,res){
db.driver.collectionNames(function(e,names){
res.json(names);
})
});
app.get('/collections/:name',function(req,res){
var collection = db.get(req.params.name);
collection.find({},{limit:20},function(e,docs){
res.json(docs);
})
});
Express conveniently supports other HTTP verbs like post and update. In the case of setting up a post route we write this:
app.post('product/:id',function(req,res) {...});
Express also has support for middeware. Middleware is just a request function handler with three parameters: request
, response
, and next
. For example:
app.post('product/:id', authenticateUser, validateProduct, addProduct);
function authenticateUser(req,res, next) {
//check req.session for authentication
next();
}
function validateProduct (req, res, next) {
//validate submitted data
next();
}
function addProduct (req, res) {
//save data to database
}
validateProduct and authenticateProduct are middleware. They are usually put into separate file (or files) in a big projects.
Another way to set up middle ware in Express application is to use use()
function. For example earlier we did this for static assets:
app.use(express.static(__dirname + '/public'));
We can also do it for error handlers:
app.use(errorHandler);
Assuming you have mongoDB installed this app will connect to it (localhost:27017) and display collection name and items in collections. To start mongo server:
$ mongod
to run app (keep the mongod terminal window open):
$ node .
or
$ node index.js
To see the app working, open http://localhost:3000 in Chrome with JSONViewer extension (to render JSON nicely).
Simple enough.. Thanks anyway.
Very informative article, I have few questions on Express Js:
1. How productive is it?
2.Performance
3.Security
Huh?
You’re using the underlying mongo driver in most of the examples. That’s not what I call an example of “a simple rest api with monk…”
Hi Kipper,
My please sir.
Straight forward and completely to the point. 5 minutes reading this and I already understand how to use middleware, serve static content, use url address parameters and connect to mongo. completely blows out the several days I spent elsewhere hunting for the same information!
Well done to the author, succinct and clear.
Great post. Thanks!
I can’t tell you how many stupid and over-complicated tuts I put myself through before stumbling onto this one. Thank you so much, and please keep them coming!!!!!