I got help from many people here, and now I want to contribute back. For those who are having trouble making a Node.js server work with MongoDB, here is what I've done.
This was originally posted by the question asker. A mod asked him in the comments to post it as an answer, but got no response. So, I cleaned it up and am posting it myself.
When you look at the code, you will notice that the createServer
code is inside db.open
. It won't work if you reverse it. Also, do not close the db connection. Otherwise, after the first time, the db connection will not be opened again. (Of course, db.open
is declared outside of createServer
.) I have no clue why createServer
is inside db.open
. I guess it may have to do with not opening too many db connections?
Also, one problem I face is that when I run it via SSH, even if I run the server in the background (e.g. $ node server.js &
), after 2.5 hours, the server dies (not the instance though). I am not sure if it is because of terminal connection or what.
Here is the procedure & code
Environment: EC2, AMS-Linux-AMI
Purpose: Take an HTTP request and log the query, IP and timestamp into MongoDB.
Steps
1) After creating the instance (server), install gcc.
$ yum install gcc-c++
2) Download Node.js files and unzip them. (I used version 2.6.)
$ curl -O http://nodejs.org/dist/node-v0.2.6.tar.gz
$ tar -xzf node-v0.2.6.tar.gz
I renamed the unzipped folder to just "nodejs"
$ cd nodejs
$ sudo ./configure --without-ssl
$ sudo make
$ sudo make install
make
takes a long while.... After that you can try running the sample in nodejs.org
3) Install MongoDB. I installed version 1.6.5, not 1.7.
$ curl -O http://fastdl.mongodb.org/linux/mongodb-linux-x86_64-1.6.5.tgz
$ tar -xzf mongodb-linux-x86_64-1.6.5.tgz
$ sudo mkdir /data/db/r01/
I renamed the folder to "mongodb"
Run the db process:
$ ./mongodb/bin/mongod --dbpath /data/db/r01/
Then if you like, you can run and try out the command line. Refer to MongoDB's website.
4) I recommend that you create your own AIM based on your instance. It will take 20 minutes. Then, recreate the install and run MongoDB again.
5) Install node-mongodb-native
$ curl -O https://download.github.com/christkv-node-mongodb-native-V0.8.1-91-g54525d8.tar.gz
$ tar -xzf christkv-node-mongodb-native-V0.8.1-91-g54525d8.tar.gz
I renamed the folder to node-mongodb-native
$ cd node-mongodb-native
$ make
6) Here is the code for the server:
GLOBAL.DEBUG = true;
global.inData = '';
var http = require('http');
sys = require("sys");
/* set up DB */
var Db = require('./node-mongodb-native/lib/mongodb').Db,
Connection = require('./node-mongodb-native/lib/mongodb').Connection,
Server = require('./node-mongodb-native/lib/mongodb').Server,
BSON = require('./node-mongodb-native/lib/mongodb').BSONNative;
var host = process.env['MONGO_NODE_DRIVER_HOST'] != null ? process.env['MONGO_NODE_DRIVER_HOST'] : 'localhost';
var port = process.env['MONGO_NODE_DRIVER_PORT'] != null ? process.env['MONGO_NODE_DRIVER_PORT'] : Connection.DEFAULT_PORT;
var db = new Db('test01', new Server(host, port, {}), {native_parser:true});
db.open(function(err, db) {
http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/plain'});
global.inData = {'p':'', 'url':''};
// get IP address
var ipAddress = req.connection.remoteAddress;
global.inData.ip = ipAddress;
// date time
var d = new Date();
var ts = d.valueOf();
global.inData.ts = ts;
// get the http query
var qs = {};
qs = require('url').parse(req.url, true);
if (qs.query !== null) {
for (var key in qs.query) {
if (key == 'p') {
global.inData.p = qs.query[key];
}
if (key == 'url') {
global.inData.url = qs.query[key];
}
}
}
if (global.inData.p == '' && global.inData.url == '') {
res.end("");
} else {
db.collection('clickCount', function(err, collection) {
if (err) {
console.log('is error \n' + err);
}
collection.insert({'p':global.inData.p,
'url':global.inData.url,
'ip':global.inData.ip,
'ts':global.inData.ts});
res.end("");
//db.close(); // DO NOT CLOSE THE CONNECTION
});
}
}).listen(8080);
});
console.log('Server running at whatever host :8080');
This may not be perfect code, but it runs. I'm still not used to the "nested" or LISP kind of coding style. That's why I cheated and used global.inData
to pass data along. :)
Don't forget to put res.end("")
in the appropriate location (where you think the HTTP request call should be ended).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With