diff --git a/src/database/mongo.js b/src/database/mongo.js index e792d41b1a..368bfae918 100644 --- a/src/database/mongo.js +++ b/src/database/mongo.js @@ -35,6 +35,11 @@ db: db }); + require('./mongo/main')(db, module); + require('./mongo/hash')(db, module); + require('./mongo/sets')(db, module); + require('./mongo/sorted')(db, module); + require('./mongo/list')(db, module); if(nconf.get('mongo:password') && nconf.get('mongo:username')) { db.authenticate(nconf.get('mongo:username'), nconf.get('mongo:password'), function (err) { @@ -75,14 +80,8 @@ }); }; - module.close = function() { - db.close(); - }; - - // - // helper functions - // - function findItem(data, key) { + var helpers = {}; + helpers.findItem = function(data, key) { if(!data) { return null; } @@ -98,9 +97,9 @@ } } return null; - } + }; - function fieldToString(field) { + helpers.fieldToString = function(field) { if(field === null || field === undefined) { return field; } @@ -111,616 +110,25 @@ // if there is a '.' in the field name it inserts subdocument in mongo, replace '.'s with \uff0E field = field.replace(/\./g, '\uff0E'); return field; - } + }; - function toString(value) { + helpers.valueToString = function(value) { if(value === null || value === undefined) { return value; } return value.toString(); - } + }; - function done(cb) { + helpers.done = function(cb) { return function(err, result) { if (typeof cb === 'function') { cb(err, result); } }; - } - - // - // Exported functions - // - - module.searchIndex = function(key, content, id) { - var data = { - id:id, - key:key, - content:content - }; - - db.collection('search').update({id:id, key:key}, {$set:data}, {upsert:true, w: 1}, function(err, result) { - if(err) { - winston.error('Error indexing ' + err.message); - } - }); - }; - - module.search = function(key, term, limit, callback) { - db.command({text:'search' , search: term, filter: {key:key}, limit: limit }, function(err, result) { - if(err) { - return callback(err); - } - - if(!result || !result.results || !result.results.length) { - return callback(null, []); - } - - var data = result.results.map(function(item) { - return item.obj.id; - }); - callback(null, data); - }); - }; - - module.searchRemove = function(key, id, callback) { - db.collection('search').remove({id:id, key:key}, done(callback)); - }; - - module.flushdb = function(callback) { - db.dropDatabase(done(callback)); - }; - - module.info = function(callback) { - db.stats({scale:1024}, function(err, stats) { - if(err) { - return callback(err); - } - - stats.avgObjSize = (stats.avgObjSize / 1024).toFixed(2); - - stats.raw = JSON.stringify(stats, null, 4); - - stats.mongo = true; - - callback(null, stats); - }); - }; - - // key - - module.exists = function(key, callback) { - db.collection('objects').findOne({_key:key}, function(err, item) { - callback(err, item !== undefined && item !== null); - }); - }; - - module.delete = function(key, callback) { - db.collection('objects').remove({_key:key}, done(callback)); - }; - - module.get = function(key, callback) { - module.getObjectField(key, 'value', callback); - }; - - module.set = function(key, value, callback) { - var data = {value:value}; - module.setObject(key, data, callback); - }; - - module.rename = function(oldKey, newKey, callback) { - db.collection('objects').update({_key: oldKey}, {$set:{_key: newKey}}, done(callback)); - }; - - module.expire = function(key, seconds, callback) { - module.expireAt(key, Math.round(Date.now() / 1000) + seconds, callback); - }; - - module.expireAt = function(key, timestamp, callback) { - module.setObjectField(key, 'expireAt', new Date(timestamp * 1000), callback); - }; - - //hashes - module.setObject = function(key, data, callback) { - data._key = key; - db.collection('objects').update({_key:key}, {$set:data}, {upsert:true, w: 1}, done(callback)); - }; - - module.setObjectField = function(key, field, value, callback) { - var data = {}; - field = fieldToString(field); - data[field] = value; - module.setObject(key, data, callback); - }; - - module.getObject = function(key, callback) { - db.collection('objects').findOne({_key:key}, {_id:0, _key:0}, callback); - }; - - module.getObjects = function(keys, callback) { - - db.collection('objects').find({_key:{$in:keys}}, {_id:0}).toArray(function(err, data) { - - if(err) { - return callback(err); - } - - var returnData = []; - - for(var i=0; i= 0) || (start >= 0 && stop < 0)) { - skip = 0; - limit = Math.pow(2, 31) - 2; - splice = true; - } else if (start > stop) { - return callback(null, []); - } - - db.collection('objects').findOne({_key:key}, { array: { $slice: [skip, limit] }}, function(err, data) { - if(err || !(data && data.array)) { - return callback(err, []); - } - - if(splice) { - - if(start < 0) { - start = data.array.length - Math.abs(start); - } - - if(stop < 0) { - stop = data.array.length - Math.abs(stop); - } - - if(start > stop) { - return callback(null, []); - } - - var howMany = stop - start + 1; - if(start !== 0 || howMany !== data.array.length) { - data.array = data.array.splice(start, howMany); - } - } - - callback(null, data.array); - }); }; + module.helpers = module.helpers || {}; + module.helpers.mongo = helpers; }(exports)); diff --git a/src/database/mongo/hash.js b/src/database/mongo/hash.js new file mode 100644 index 0000000000..72cd9d6170 --- /dev/null +++ b/src/database/mongo/hash.js @@ -0,0 +1,159 @@ +"use strict"; + +module.exports = function(db, module) { + var helpers = module.helpers.mongo; + + module.setObject = function(key, data, callback) { + data._key = key; + db.collection('objects').update({_key:key}, {$set:data}, {upsert:true, w: 1}, helpers.done(callback)); + }; + + module.setObjectField = function(key, field, value, callback) { + var data = {}; + field = helpers.fieldToString(field); + data[field] = value; + module.setObject(key, data, callback); + }; + + module.getObject = function(key, callback) { + db.collection('objects').findOne({_key:key}, {_id:0, _key:0}, callback); + }; + + module.getObjects = function(keys, callback) { + + db.collection('objects').find({_key:{$in:keys}}, {_id:0}).toArray(function(err, data) { + + if(err) { + return callback(err); + } + + var returnData = []; + + for(var i=0; i= 0) || (start >= 0 && stop < 0)) { + skip = 0; + limit = Math.pow(2, 31) - 2; + splice = true; + } else if (start > stop) { + return callback(null, []); + } + + db.collection('objects').findOne({_key:key}, { array: { $slice: [skip, limit] }}, function(err, data) { + if(err || !(data && data.array)) { + return callback(err, []); + } + + if(splice) { + + if(start < 0) { + start = data.array.length - Math.abs(start); + } + + if(stop < 0) { + stop = data.array.length - Math.abs(stop); + } + + if(start > stop) { + return callback(null, []); + } + + var howMany = stop - start + 1; + if(start !== 0 || howMany !== data.array.length) { + data.array = data.array.splice(start, howMany); + } + } + + callback(null, data.array); + }); + }; +}; \ No newline at end of file diff --git a/src/database/mongo/main.js b/src/database/mongo/main.js new file mode 100644 index 0000000000..203c26af26 --- /dev/null +++ b/src/database/mongo/main.js @@ -0,0 +1,96 @@ +"use strict"; + +var winston = require('winston'); + +module.exports = function(db, module) { + var helpers = module.helpers.mongo; + + module.close = function() { + db.close(); + }; + + module.searchIndex = function(key, content, id) { + var data = { + id:id, + key:key, + content:content + }; + + db.collection('search').update({id:id, key:key}, {$set:data}, {upsert:true, w: 1}, function(err, result) { + if(err) { + winston.error('Error indexing ' + err.message); + } + }); + }; + + module.search = function(key, term, limit, callback) { + db.command({text:'search' , search: term, filter: {key:key}, limit: limit }, function(err, result) { + if(err) { + return callback(err); + } + + if(!result || !result.results || !result.results.length) { + return callback(null, []); + } + + var data = result.results.map(function(item) { + return item.obj.id; + }); + + callback(null, data); + }); + }; + + module.searchRemove = function(key, id, callback) { + db.collection('search').remove({id:id, key:key}, helpers.done(callback)); + }; + + module.flushdb = function(callback) { + db.dropDatabase(helpers.done(callback)); + }; + + module.info = function(callback) { + db.stats({scale:1024}, function(err, stats) { + if(err) { + return callback(err); + } + + stats.avgObjSize = (stats.avgObjSize / 1024).toFixed(2); + stats.raw = JSON.stringify(stats, null, 4); + stats.mongo = true; + + callback(null, stats); + }); + }; + + module.exists = function(key, callback) { + db.collection('objects').findOne({_key:key}, function(err, item) { + callback(err, item !== undefined && item !== null); + }); + }; + + module.delete = function(key, callback) { + db.collection('objects').remove({_key:key}, helpers.done(callback)); + }; + + module.get = function(key, callback) { + module.getObjectField(key, 'value', callback); + }; + + module.set = function(key, value, callback) { + var data = {value:value}; + module.setObject(key, data, callback); + }; + + module.rename = function(oldKey, newKey, callback) { + db.collection('objects').update({_key: oldKey}, {$set:{_key: newKey}}, helpers.done(callback)); + }; + + module.expire = function(key, seconds, callback) { + module.expireAt(key, Math.round(Date.now() / 1000) + seconds, callback); + }; + + module.expireAt = function(key, timestamp, callback) { + module.setObjectField(key, 'expireAt', new Date(timestamp * 1000), callback); + }; +}; \ No newline at end of file diff --git a/src/database/mongo/sets.js b/src/database/mongo/sets.js new file mode 100644 index 0000000000..73b4e6428b --- /dev/null +++ b/src/database/mongo/sets.js @@ -0,0 +1,118 @@ +"use strict"; + +module.exports = function(db, module) { + var helpers = module.helpers.mongo; + + module.setAdd = function(key, value, callback) { + if(!Array.isArray(value)) { + value = [value]; + } + + value.forEach(function(element, index, array) { + array[index] = helpers.valueToString(element); + }); + + db.collection('objects').update({ + _key: key + }, { + $addToSet: { + members: { + $each: value + } + } + }, { + upsert: true, + w: 1 + }, helpers.done(callback)); + }; + + module.setRemove = function(key, value, callback) { + if(!Array.isArray(value)) { + value = [value]; + } + + value.forEach(function(element, index, array) { + array[index] = helpers.valueToString(element); + }); + + db.collection('objects').update({_key: key}, {$pullAll: {members: value}}, helpers.done(callback)); + }; + + module.isSetMember = function(key, value, callback) { + value = helpers.valueToString(value); + + db.collection('objects').findOne({_key:key, members: value}, function(err, item) { + callback(err, item !== null && item !== undefined); + }); + }; + + module.isSetMembers = function(key, values, callback) { + for (var i=0; i