Skip to content
This repository has been archived by the owner on Nov 27, 2018. It is now read-only.

Using MongoDB for persistent storage

Jason Mulligan edited this page Jul 15, 2013 · 16 revisions

Using MongoDB for persistent storage

abaaso provides a rich NoSQL database in RAM that works well on a Client (desktop, tablet, smartphone, etc.), and on the Server (node.js), but one important feature was missing: "good" persistent storage. HTML5 storage APIs where supported from inception, but that's not ideal for the Server, even with a localStorage shim provided by a node module.

This is where MongoDB comes into the picture. It's great at the type of work abaaso does on a Client, and is ideal for persistent storage on the Server, where other processes might need access to the data.

So why not simply use only MongoDB on the Server? abaaso in front of MongoDB provides many benefits, such as lower latency, & "repeating patterns"; if you only have to write "one style" everywhere, it's much easier to be consistent and avoid context switches.

Creating a RESTful CRUD API around a DataStore requires minimal effort. The following sample application uses turtle.io for the Server, and a DataStore wired to MongoDB for a users database.

Server

var $       = require("abaaso"),
    turtle  = require("turtle.io"),
    server  = new turtle(),
    config, prepare, users;

// Server config
config = {
	default : "myapp.com",
	ps      : 10,
	uid     : 100,
	port    : 80,
	root    : "/var/www",
	vhosts  : {
		"myapp.com"      : "myapp.com",
		"www.myapp.com"  : "myapp.com",
		"blog.myapp.com" : "blog.myapp.com",
		"api.myapp.com"  : "api.myapp.com" // Overridden by custom routes
	}
}

// Prepares API response body
prepare = function (data, status, error) {
	data   = data   || null;
	status = status || 200;
	error  = error  || null;
	return {data: data, error: error, status: status};
};

// Creating a DataStore
users = $.data({id: "users"}, null, {autosave: true, events: false, key: "id", mongodb: "mongodb://localhost/myapp"});

// Setting routes
server.get("/", function (req, res, timer) {
	server.respond(req, res, prepare(["/users"], 200), 200, {Allow: "GET, POST"}, timer);
}, "api.myapp.com");

server.get("/users", function (req, res, timer) {
	server.respond(req, res, prepare(users.data.dump(), 200), 200, {Allow: "GET, POST"}, timer);
}, "api.myapp.com");

server.post("/users", function (req, res, timer) {
	users.data.set(null, JSON.parse(req.body)).then(function (record) {
		server.respond(req, res, prepare({next: "/users/" + record.key}, 201), 201, {Allow: "GET, POST"}, timer);
	}, function (e) {
		server.respond(req, res, prepare(null, 500, e), 500, {Allow: "GET, POST"}, timer);
	});
}, "api.myapp.com");

server.get("/users/([a-f0-9-]{36})", function (req, res, timer) {
	var record = users.data.get(req.url.replace(/.*\//, ""));

	if (record) {
		server.respond(req, res, prepare(record.data, 200), 200, {Allow: "GET, PUT, DELETE"}, timer);
	}
	else {
		server.respond(req, res, prepare(null, 404, "Not found"), 404, null, timer);
	}
}, "api.myapp.com");

server.put("/users/([a-f0-9-]{36})", function (req, res, timer) {
	users.data.set(req.url.replace(/.*\//, ""), JSON.parse(req.body)).then(function (record) {
		server.respond(req, res, null, 204, {Allow: "GET, PUT, DELETE"}, timer);
	}, function (e) {
		server.respond(req, res, prepare(null, 500, e), 500, {Allow: "GET, PUT, DELETE"}, timer);
	});
}, "api.myapp.com");

server.delete("/users/([a-f0-9-]{36})", function (req, res, timer) {
	users.data.del(req.url.replace(/.*\//, "")).then(function (record) {
		server.respond(req, res, null, 200, null, timer);
	}, function (e) {
		server.respond(req, res, prepare(null, 500, e), 500, {Allow: "GET, PUT, DELETE"}, timer);
	});
}, "api.myapp.com");

// Retrieving data from MongoDB & starting server
users.data.restore().then(function () {
	server.start(config);
}, function (e) {
	console.log(e);
});

Client

var users = $.data({id: "users"}, null, {events: false, key: "id", source: "data"});

users.data.setUri("http://api.myapp.com/users").then(function (recs) {
	// recs is an Array of records retrieved from the API
}, function (e) {
	// handle e!
});

Notes

  • If you where to use multiple databases for multiple collections, you could handle it with a $.when() for the multiple data.restore() statements.