node.js + express + mongodb


CV.js, June 19 2013

Michael Holroyd

Title

What is this stuff?


node.js

server-side event-driven javascript


express

a minimialist web-framework for node.js


mongodb

a schemaless document database

Why node.js?

  • Javascript!

  • Non-blocking code makes very efficient use of single-thread

  • npm is an exceptional package manager

node.js webserver


This simple web server written in node responds with "Hello World" for every request.


         1 var http = require('http');
 2 http.createServer(function (req, res) {
 3   res.writeHead(200, {'Content-Type': 'text/plain'});
 4   res.end('Hello World\n');
 5 }).listen(1337, '127.0.0.1');


Why express?

  • Handles common server patterns

  • Minimalist. No models/auth/etc

  • Middleware to handle requests

express webserver

Same webserver as before. Takes care of routes, http verbs, content-type, parameters, parsing headers, etc.


 1 var express = require('express');
 2 var app = express();
 3 app.get('/', function(req, res){
 4   res.send('Hello World');
 5 });
 6 app.listen(1337);
            

middleware

Easily pass each request through a series of filters (middleware).

var allowCrossDomain = function(req, res, next) {
  res.header('Access-Control-Allow-Origin', '*');
  res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
  res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, Content-Length, X-Requested-With');

// intercept OPTIONS method if ('OPTIONS' === req.method) { res.send(200); } else { next(); } };

app.configure(function(){ app.use(express.logger()); app.use(allowCrossDomain); });

Why mongoDB?

  • Stores JSON objects

  • Integrates nicely into node.js

  • Don't have to think about schema ahead of time

mongoDB

Example API that returns the whole database as JSON


var mongo = require('mongodb');

mongo.connect(mongoUri,{auto_reconnect:true},function(err, db){ app.get('/firehose', function(req, response) { db.collection('twists', function(err, twists) { twists.find({}).sort({"created_at":-1}).toArray(function(err, twistArray) { response.send(twistArray); }); }); }); }


each call is non-blocking

mongoDB

Group twists from the same user together and update records

var r = db.twists.aggregate({
    $group: {
        _id: "$identifier",
        twistsPerDevice: { $sum: 1 },
        twhandle: { $max: "$twhandle" }
    }
});

r.result.map(function(o){ if (o.twhandle) { db.twists.update( { identifier: o._id }, { twhandle: o.twhandle } ); } });

What about the HTML?



Lots of template langauges



}


  mustache.js

     Logic-less templates

mustache.js



var view = {
  title: "Joe",
  calc: function () {
    return 2 + 4;
  }
};

var output = mustache.render("{{title}} spends {{calc}}", view);

mustache.js


var mustacheTwist = mustache.compile(fs.readFileSync("twist.html",'utf8'));
app.get('/:id', function(req, response) { db.collection('twists', function(err, twists) { var c = twists.find({_id: req.params.id}); c.nextObject(function(err,twist){

var view = { server: "focustwist.com", twist_id: req.params.id, created_at: moment(twist.created_at).fromNow(), twhandle: twist.twhandle, }; response.send(mustacheTwist(view)); }); }); });

Static HTML and assets



Express middleware again, express.static()


app.configure(function(){
    app.use(express.logger());
    app.use(express.bodyParser());
    app.use(allowCrossDomain);
    app.use(express.static(__dirname + "/public"));
  });

Deploying



Platform as a Service
Free web dyno for development
$34.50/month for a second dyno

 
Managed mongoDB as a service
Free starter plan for up to 500MB
$10/month for 20GB


Performance



Rough tests show free plan can handle about


~1,200 simultaneous users
~500 hits per second
(read-heavy workload)



before slowing down

Thanks


Tools:
http://nodejs.org/
http://expressjs.com/
http://www.mongodb.org/
http://mustache.github.io/

Deploying:
https://www.heroku.com/
https://www.mongolab.com

Michael Holroyd
http://meekohi.com
http://arqball.com
http://focustwist.com

node.js + express + mongodb

By Michael Holroyd

node.js + express + mongodb

  • 2,678