diff --git a/README.md b/README.md index 98bc508..46bd48c 100644 --- a/README.md +++ b/README.md @@ -154,6 +154,28 @@ or post. All of which are optional except `type` with very logical default values. +### MongoDB + +To use mongodb storage you must install the 'mongodb' pachage in npm + +`npm install mongodb` + +Once you've done that, your config section should look like: + +``` json +{ + "type": "mongodb", + "connectionUrl": "mongodb://localhost:27017/database" +} +``` + +You can also just set the environment variable for `DATABASE_URL` to your database connection url. + +Unlike with postgres you do NOT have to create the table in your mongo database prior to running. + +You can also set an `expire` option to the number of seconds to expire keys in. +This is off by default, but will constantly kick back expirations on each view or post. + ### Memcached To use memcache storage you must install the `memcached` package via npm diff --git a/lib/document_stores/mongo.js b/lib/document_stores/mongo.js new file mode 100644 index 0000000..502a508 --- /dev/null +++ b/lib/document_stores/mongo.js @@ -0,0 +1,88 @@ + + +var MongoClient = require('mongodb').MongoClient, + winston = require('winston'); + +var MongoDocumentStore = function (options) { + this.expire = options.expire; + this.connectionUrl = process.env.DATABASE_URl || options.connectionUrl; +}; + +MongoDocumentStore.prototype.set = function (key, data, callback, skipExpire) { + var now = Math.floor(new Date().getTime() / 1000), + that = this; + + this.safeConnect(function (err, db) { + if (err) + return callback(false); + + db.collection('entries').update({ + 'entry_id': key, + $or: [ + { expiration: -1 }, + { expiration: { $gt: now } } + ] + }, { + 'entry_id': key, + 'value': data, + 'expiration': that.expire && !skipExpire ? that.expire + now : -1 + }, { + upsert: true + }, function (err, existing) { + if (err) { + winston.error('error persisting value to mongodb', { error: err }); + return callback(false); + } + + callback(true); + }); + }); +}; + +MongoDocumentStore.prototype.get = function (key, callback, skipExpire) { + var now = Math.floor(new Date().getTime() / 1000), + that = this; + + this.safeConnect(function (err, db) { + if (err) + return callback(false); + + db.collection('entries').findOne({ + 'entry_id': key, + $or: [ + { expiration: -1 }, + { expiration: { $gt: now } } + ] + }, function (err, entry) { + if (err) { + winston.error('error persisting value to mongodb', { error: err }); + return callback(false); + } + + callback(entry === null ? false : entry.value); + + if (entry !== null && entry.expiration !== -1 && that.expire && !skipExpire) { + db.collection('entries').update({ + 'entry_id': key + }, { + $set: { + 'expiration': that.expire + now + } + }, function (err, result) { }); + } + }); + }); +}; + +MongoDocumentStore.prototype.safeConnect = function (callback) { + MongoClient.connect(this.connectionUrl, function (err, db) { + if (err) { + winston.error('error connecting to mongodb', { error: err }); + callback(err); + } else { + callback(undefined, db); + } + }); +}; + +module.exports = MongoDocumentStore;