Comparing version 3.1.8 to 3.1.9
@@ -16,4 +16,4 @@ 'use strict'; | ||
this.store = {}; | ||
options = options || {cacheSize: 256, ttl: 30000}; | ||
this.size = options.cacheSize || 256; | ||
options = options || {cacheSize: 4096, ttl: 30000}; | ||
this.size = options.cacheSize || 4096; | ||
this.ttl = options.ttl || 30000; | ||
@@ -20,0 +20,0 @@ this.keys = 0; |
240
lib/index.js
@@ -8,11 +8,16 @@ 'use strict'; | ||
var Cursor = mongodb.Cursor; | ||
// helpers | ||
var arrayHelper = require('./helpers/arrays'); | ||
var parallelHelper = require('./helpers/parallel'); | ||
var Cache = require('./helpers/cache'); | ||
// protos | ||
var model = require('./protos/model'); | ||
var schemaModel = require('./protos/schemamodel'); | ||
var embeddedSchemaModel = require('./protos/embedschemamodel'); | ||
var view = require('./protos/view'); | ||
// common | ||
var common = require('./protos/common'); | ||
var schema = new (require('jsonschema').Environment)(); | ||
var snapshotsCache = new Cache(); | ||
@@ -29,3 +34,3 @@ // lazy connector | ||
var extractOption = common.extractOption; | ||
var extractOption = common.extractOption; | ||
@@ -151,3 +156,5 @@ /** | ||
}, 300); | ||
} else if (!_connected) { | ||
} | ||
if (!_connected) { | ||
if (!_url) { | ||
@@ -180,14 +187,14 @@ return callback('No Connection defined.'); | ||
return null; | ||
} else { | ||
if (_collections[collection_name]) { | ||
return callback(null, _collections[collection_name]); | ||
} else { | ||
return ODM.db.collection(collection_name, options, function (err, collection) { | ||
if (!err) { | ||
_collections[collection_name] = collection; | ||
} | ||
return callback(err, collection); | ||
}); | ||
} | ||
if (_collections[collection_name]) { | ||
return callback(null, _collections[collection_name]); | ||
} | ||
ODM.db.collection(collection_name, options, function (err, collection) { | ||
if (!err) { | ||
_collections[collection_name] = collection; | ||
} | ||
} | ||
return callback(err, collection); | ||
}); | ||
}, | ||
@@ -241,5 +248,5 @@ | ||
return callback(null, cursor); | ||
} else { | ||
return callback('Cursor is closed'); | ||
} | ||
return callback('Cursor is closed'); | ||
} | ||
@@ -372,2 +379,19 @@ | ||
snapshot: function (collection_name, oid, fields, options, callback) { | ||
var storeSnapshot = function (txdocument) { | ||
if (options.transient === true) { | ||
snapshotsCache.set(oid.toHexString(), txdocument); | ||
callback(null); | ||
} else { | ||
ODM.collection('snapshots', options, function (err, txcollection) { | ||
if (err) { | ||
return callback(err); | ||
} | ||
options.safe = _safeOptions; | ||
return txcollection.save(txdocument, options, callback); | ||
}); | ||
} | ||
}; | ||
ODM.collection(collection_name, options, function (err, collection) { | ||
@@ -387,15 +411,3 @@ if (err) { | ||
return ODM.collection('snapshots', options, function (err, txcollection) { | ||
if (err) { | ||
return callback(err); | ||
} | ||
options.safe = _safeOptions; | ||
var txdocument = { | ||
_id: oid, | ||
fields: fields, | ||
doc: document | ||
}; | ||
return txcollection.save(txdocument, options, callback); | ||
}); | ||
storeSnapshot({_id: oid, fields: fields, doc: document}); | ||
}); | ||
@@ -415,3 +427,32 @@ }); | ||
revert: function (collection_name, oid, options, callback) { | ||
ODM.collection('snapshots', options, function (err, txcollection) { | ||
var loadSnapshot = function (callback) { | ||
if (options.transient === true) { | ||
callback(null, snapshotsCache.get(oid.toHexString())); | ||
} else { | ||
ODM.collection('snapshots', options, function (err, txcollection) { | ||
if (err) { | ||
return callback(err); | ||
} | ||
return txcollection.findOne({_id: oid}, {}, options, callback); | ||
}); | ||
} | ||
}; | ||
var cleanSnapshot = function (callback) { | ||
if (options.transient === true) { | ||
callback(null); | ||
} else { | ||
ODM.collection('snapshots', options, function (err, txcollection) { | ||
if (err) { | ||
return callback(err); | ||
} | ||
txcollection.remove({_id: oid}, options, callback); | ||
}); | ||
} | ||
}; | ||
loadSnapshot(function (err, document) { | ||
if (err) { | ||
@@ -421,3 +462,7 @@ return callback(err); | ||
return txcollection.findOne({_id: oid}, {}, options, function (err, document) { | ||
if (document === null) { | ||
return callback('not found'); | ||
} | ||
return ODM.collection(collection_name, options, function (err, collection) { | ||
if (err) { | ||
@@ -427,64 +472,54 @@ return callback(err); | ||
if (document === null) { | ||
return callback('not found'); | ||
} | ||
options.safe = _safeOptions; | ||
// was this snapshot a full doc or partial? | ||
var fields = Object.keys(document.fields); | ||
return ODM.collection(collection_name, options, function (err, collection) { | ||
if (err) { | ||
return callback(err); | ||
if (fields.length > 0) { | ||
// partial | ||
// remove _id | ||
delete document.doc._id; | ||
var update = {$set: document.doc}; | ||
// generate unset list | ||
var docFields = Object.keys(document.doc); | ||
var i, j; | ||
for (i = 0; i < docFields.length; i++) { | ||
for (j = 0; j < fields.length; j++) { | ||
if (docFields[i] === fields[j]) { | ||
fields.splice(j, 1); | ||
break; | ||
} | ||
} | ||
} | ||
options.safe = _safeOptions; | ||
// was this snapshot a full doc or partial? | ||
var fields = Object.keys(document.fields); | ||
if (fields.length > 0) { | ||
// partial | ||
// remove _id | ||
delete document.doc._id; | ||
var update = {$set: document.doc}; | ||
update.$unset = {}; | ||
for (j = 0; j < fields.length; j++) { | ||
update.$unset[fields[j]] = 1; | ||
} | ||
} | ||
// generate unset list | ||
var docFields = Object.keys(document.doc); | ||
var i, j; | ||
for (i = 0; i < docFields.length; i++) { | ||
for (j = 0; j < fields.length; j++) { | ||
if (docFields[i] === fields[j]) { | ||
fields.splice(j, 1); | ||
break; | ||
} | ||
} | ||
collection.update({_id: oid}, update, options, function (err) { | ||
if (err) { | ||
return callback(err); | ||
} | ||
if (fields.length > 0) { | ||
update.$unset = {}; | ||
for (j = 0; j < fields.length; j++) { | ||
update.$unset[fields[j]] = 1; | ||
} | ||
// clean up | ||
delete options.safe; | ||
return cleanSnapshot(callback); | ||
}); | ||
} else { | ||
// full | ||
// ensure _id | ||
document.doc._id = oid; | ||
collection.save(document.doc, options, function (err) { | ||
if (err) { | ||
return callback(err); | ||
} | ||
collection.update({_id: oid}, update, options, function (err) { | ||
if (err) { | ||
return callback(err); | ||
} | ||
// clean up | ||
delete options.safe; | ||
return txcollection.remove({_id: oid}, options, callback); | ||
}); | ||
} else { | ||
// full | ||
// ensure _id | ||
document.doc._id = oid; | ||
collection.save(document.doc, options, function (err) { | ||
if (err) { | ||
return callback(err); | ||
} | ||
// clean up | ||
delete options.safe; | ||
return txcollection.remove({_id: oid}, options, callback); | ||
}); | ||
} | ||
}); | ||
// clean up | ||
delete options.safe; | ||
return cleanSnapshot(callback); | ||
}); | ||
} | ||
}); | ||
@@ -504,9 +539,13 @@ }); | ||
flush: function (collection_name, oid, options, callback) { | ||
ODM.collection('snapshots', options, function (err, txcollection) { | ||
if (err) { | ||
return callback(err); | ||
} | ||
if (options.transient === true) { | ||
snapshotsCache.del(oid.toHexString()); | ||
} else { | ||
ODM.collection('snapshots', options, function (err, txcollection) { | ||
if (err) { | ||
return callback(err); | ||
} | ||
return txcollection.remove({_id: oid}, options, callback); | ||
}); | ||
return txcollection.remove({_id: oid}, options, callback); | ||
}); | ||
} | ||
}, | ||
@@ -574,2 +613,14 @@ | ||
/** | ||
* Creates a new View Class based on a Model and Mappings | ||
* | ||
* @static | ||
* @memberOf ODM | ||
* @param {Model|SchemaModel} modelClass | ||
* @param {Object} mappings | ||
* | ||
* @return {Function} | ||
*/ | ||
view: view, | ||
subgraph: function (name, options, schemas) { | ||
@@ -725,3 +776,8 @@ | ||
*/ | ||
array: arrayHelper | ||
array: arrayHelper, | ||
/** | ||
* Helper functions to work with parallel queries | ||
*/ | ||
parallel: parallelHelper | ||
}; | ||
@@ -728,0 +784,0 @@ |
@@ -40,6 +40,37 @@ 'use strict'; | ||
/** | ||
* @private | ||
* allows to call a callback after n times with proper error handling. | ||
* | ||
* @param times | ||
* @param callback | ||
*/ | ||
function after(times, callback) { | ||
// special case when times is zero call right away and exit | ||
if (times === 0) { | ||
return callback(null); | ||
} | ||
var calls = times; | ||
var gotError = false; | ||
return function (error) { | ||
if (error) { | ||
gotError = true; | ||
return callback(error); | ||
} | ||
if (!gotError && --calls === 0) { | ||
return callback(null); | ||
} | ||
}; | ||
} | ||
module.exports = { | ||
extractOption: extractOption, | ||
getOption: getOption | ||
getOption: getOption, | ||
after: after | ||
}; | ||
@@ -63,5 +63,4 @@ /** | ||
return validation; | ||
} else { | ||
return false; | ||
} | ||
return false; | ||
} | ||
@@ -73,5 +72,4 @@ } | ||
return null; | ||
} else { | ||
return true; | ||
} | ||
return true; | ||
}; | ||
@@ -78,0 +76,0 @@ |
@@ -53,2 +53,8 @@ /** | ||
/** | ||
* mongo collection | ||
* @memberOf Model | ||
*/ | ||
Object.defineProperty(Model, '$collection', {value: mongoCollection}); | ||
/** | ||
* Finds one element of this collection by the given query. | ||
@@ -277,9 +283,9 @@ * | ||
return callback(null, documentsLoaded); | ||
} else { | ||
for (i = 0, len = documentsLoaded.length; i < len; i++) { | ||
// enhance the DB document do have ODM features | ||
documentsLoaded[i][PROTO] = Model.prototype; | ||
} | ||
return callback(null, documentsLoaded); | ||
} | ||
for (i = 0, len = documentsLoaded.length; i < len; i++) { | ||
// enhance the DB document do have ODM features | ||
documentsLoaded[i][PROTO] = Model.prototype; | ||
} | ||
return callback(null, documentsLoaded); | ||
}); | ||
@@ -372,54 +378,54 @@ }; | ||
return callback(null, []); | ||
} else { | ||
// convert the orig array to an index | ||
var index = {}; | ||
var i, len; | ||
var idsToFind = []; | ||
} | ||
for (i = 0, len = ids.length; i < len; i++) { | ||
if (!(ids[i] instanceof ObjectId)) { | ||
return callback('Non ObjectId in the array'); | ||
} | ||
// convert the orig array to an index | ||
var index = {}; | ||
var i, len; | ||
var idsToFind = []; | ||
// build index for the missing data | ||
if (index[ids[i].toHexString()] === undefined) { | ||
index[ids[i].toHexString()] = [i]; | ||
idsToFind.push(ids[i]); | ||
} else { | ||
index[ids[i].toHexString()].push(i); | ||
} | ||
for (i = 0, len = ids.length; i < len; i++) { | ||
if (!(ids[i] instanceof ObjectId)) { | ||
return callback('Non ObjectId in the array'); | ||
} | ||
// no items to search | ||
if (idsToFind.length === 0) { | ||
return callback(null, []); | ||
// build index for the missing data | ||
if (index[ids[i].toHexString()] === undefined) { | ||
index[ids[i].toHexString()] = [i]; | ||
idsToFind.push(ids[i]); | ||
} else { | ||
index[ids[i].toHexString()].push(i); | ||
} | ||
} | ||
return odm.find(mongoCollection, {_id: {'$in': idsToFind}}, fields, options, function (err, documentsLoaded) { | ||
if (err) { | ||
return callback(err); | ||
} | ||
// no items to search | ||
if (idsToFind.length === 0) { | ||
return callback(null, []); | ||
} | ||
var i, j, lenI, lenJ; | ||
var result = []; | ||
return odm.find(mongoCollection, {_id: {'$in': idsToFind}}, fields, options, function (err, documentsLoaded) { | ||
if (err) { | ||
return callback(err); | ||
} | ||
// using the index we have O(2n) complexity | ||
for (i = 0, lenI = documentsLoaded.length; i < lenI; i++) { | ||
var indexes = index[documentsLoaded[i]._id.toHexString()]; | ||
for (j = 0, lenJ = indexes.length; j < lenJ; j++) { | ||
var i, j, lenI, lenJ; | ||
var result = []; | ||
if (hasFields) { | ||
if (pluck !== undefined) { | ||
result[indexes[j]] = documentsLoaded[i][pluck]; | ||
} | ||
} else { | ||
result[indexes[j]] = documentsLoaded[i]; | ||
result[indexes[j]][PROTO] = Model.prototype; | ||
// using the index we have O(2n) complexity | ||
for (i = 0, lenI = documentsLoaded.length; i < lenI; i++) { | ||
var indexes = index[documentsLoaded[i]._id.toHexString()]; | ||
for (j = 0, lenJ = indexes.length; j < lenJ; j++) { | ||
if (hasFields) { | ||
if (pluck !== undefined) { | ||
result[indexes[j]] = documentsLoaded[i][pluck]; | ||
} | ||
} else { | ||
result[indexes[j]] = documentsLoaded[i]; | ||
result[indexes[j]][PROTO] = Model.prototype; | ||
} | ||
} | ||
} | ||
return callback(null, result); | ||
}); | ||
} | ||
return callback(null, result); | ||
}); | ||
}; | ||
@@ -468,5 +474,4 @@ | ||
return Model.findOne(query, fields, options, callback); | ||
} else { | ||
return Model.find(query, fields, options, callback); | ||
} | ||
return Model.find(query, fields, options, callback); | ||
}; | ||
@@ -787,2 +792,49 @@ } | ||
/** | ||
* Prepares a find statement to run in parallel mode. | ||
* | ||
* @param {Object} query | ||
* @param {Object} [fields] | ||
* @param {Object} [options] | ||
* @return {Object} finder object | ||
*/ | ||
Model.prepareFindOne = function (query, fields, options) { | ||
return {fn: Model.findOne, query: query, fields: fields, options: options}; | ||
}; | ||
/** | ||
* Prepares a find statement to run in parallel mode. | ||
* | ||
* @param {ObjectId} id | ||
* @param {Object} [fields] | ||
* @param {Object} [options] | ||
* @return {Object} finder object | ||
*/ | ||
Model.prepareFindById = function (id, fields, options) { | ||
return {fn: Model.findById, query: id, fields: fields, options: options}; | ||
}; | ||
/** | ||
* Prepares a find statement to run in parallel mode. | ||
* | ||
* @param {Object} query | ||
* @param {Object} [fields] | ||
* @param {Object} [options] | ||
* @return {Object} finder object | ||
*/ | ||
Model.prepareFind = function (query, fields, options) { | ||
return {fn: Model.find, query: query, fields: fields, options: options}; | ||
}; | ||
/** | ||
* Prepares a find statement to run in parallel mode. | ||
* | ||
* @param {Object} [fields] | ||
* @param {Object} [options] | ||
* @return {Object} finder object | ||
*/ | ||
Model.prepareFindAll = function (fields, options) { | ||
return {fn: Model.find, query: {}, fields: fields, options: options}; | ||
}; | ||
return Model; | ||
@@ -789,0 +841,0 @@ } |
@@ -63,2 +63,8 @@ /** | ||
/** | ||
* mongo collection | ||
* @memberOf SchemaModel | ||
*/ | ||
Object.defineProperty(SchemaModel, '$collection', {value: mongoCollection}); | ||
/** | ||
* schema for embedded objects | ||
@@ -81,5 +87,4 @@ * @memberOf SchemaModel | ||
return validation; | ||
} else { | ||
return false; | ||
} | ||
return false; | ||
} | ||
@@ -91,5 +96,4 @@ } | ||
return null; | ||
} else { | ||
return true; | ||
} | ||
return true; | ||
}; | ||
@@ -344,6 +348,5 @@ | ||
return documentsLoaded.eachModel(callback); | ||
} else { | ||
// Close the cursor if done | ||
return documentsLoaded.close(callback); | ||
} | ||
// Close the cursor if done | ||
return documentsLoaded.close(callback); | ||
}); | ||
@@ -571,5 +574,4 @@ }); | ||
return SchemaModel.findOne(query, fields, options, callback); | ||
} else { | ||
return SchemaModel.find(query, fields, options, callback); | ||
} | ||
return SchemaModel.find(query, fields, options, callback); | ||
}; | ||
@@ -801,2 +803,49 @@ } | ||
/** | ||
* Prepares a find statement to run in parallel mode. | ||
* | ||
* @param {Object} query | ||
* @param {Object} [fields] | ||
* @param {Object} [options] | ||
* @return {Object} finder object | ||
*/ | ||
SchemaModel.prepareFindOne = function (query, fields, options) { | ||
return {fn: SchemaModel.findOne, query: query, fields: fields, options: options}; | ||
}; | ||
/** | ||
* Prepares a find statement to run in parallel mode. | ||
* | ||
* @param {ObjectId} id | ||
* @param {Object} [fields] | ||
* @param {Object} [options] | ||
* @return {Object} finder object | ||
*/ | ||
SchemaModel.prepareFindById = function (id, fields, options) { | ||
return {fn: SchemaModel.findById, query: id, fields: fields, options: options}; | ||
}; | ||
/** | ||
* Prepares a find statement to run in parallel mode. | ||
* | ||
* @param {Object} query | ||
* @param {Object} [fields] | ||
* @param {Object} [options] | ||
* @return {Object} finder object | ||
*/ | ||
SchemaModel.prepareFind = function (query, fields, options) { | ||
return {fn: SchemaModel.find, query: query, fields: fields, options: options}; | ||
}; | ||
/** | ||
* Prepares a find statement to run in parallel mode. | ||
* | ||
* @param {Object} [fields] | ||
* @param {Object} [options] | ||
* @return {Object} finder object | ||
*/ | ||
SchemaModel.prepareFindAll = function (fields, options) { | ||
return {fn: SchemaModel.find, query: {}, fields: fields, options: options}; | ||
}; | ||
return SchemaModel; | ||
@@ -803,0 +852,0 @@ } |
@@ -8,3 +8,3 @@ { | ||
], | ||
"version": "3.1.8", | ||
"version": "3.1.9", | ||
"engines": { | ||
@@ -11,0 +11,0 @@ "node": ">=0.4.12" |
93445
18
3066